удалить пробел в std :: string

В C ++, что является простым способом:

Эта строка std ::

\t\tHELLO WORLD\r\nHELLO\t\nWORLD     \t

В:

HELLOWORLDHELLOWORLD
21
@CashCow Я проверил его снова. Вы правы, извините.
добавлено автор tmaric, источник
@ tomislav-maric Я не думаю, что это дубликат этого сообщения, OP работал с потоком cin и таким образом использовал функции iostream.
добавлено автор Mr. Smith, источник
похожий, но не точный дубликат, поэтому не голосование закрывается.
добавлено автор CashCow, источник
добавлено автор user, источник

6 ответы

Простая комбинация std :: remove_if и станд :: строка :: стирание .

Не полностью безопасная версия

s.erase( std::remove_if( s.begin(), s.end(), ::isspace ), s.end() );

Для более безопасной версии замените :: isspace на

std::bind( std::isspace, _1, std::locale::classic() )

(Включите все соответствующие заголовки)

For a version that works with alternative character types replace with or whatever your templated character type is. You can of course also replace the locale with a different one. If you do that, beware to avoid the inefficiency of recreating the locale facet too many times.

В C ++ 11 вы можете сделать более безопасную версию в лямбда с:

[]( char ch ) { return std::isspace( ch, std::locale::classic() ); }
33
добавлено
isspace имеет UB для всех символов, кроме тех, что в базовом что-то есть. C99 §7.4/1.
добавлено автор R. Martinho Fernandes, источник
C ++ 98 делегирует поведение стандартной библиотеки C на C89, а C ++ 11 передает поведение стандартной библиотеки C на C99.
добавлено автор R. Martinho Fernandes, источник
(И обратите внимание, что это не касается многобайтовых кодировок: любой байт со значением, превышающим 0x7F в источнике, , независимо от кодировки , вызовет эту проблему; даже однобайтовые кодировки, такие как Latin-1 или Windows-1252 вызовет это. Только 7-битные кодировки, такие как ASCII, работают нормально)
добавлено автор R. Martinho Fernandes, источник
(И в качестве примечания, NBSP отсутствует в ASCII. ASCII имеет только 128 значений).
добавлено автор R. Martinho Fernandes, источник
FWIW, все пробельные символы в примере закодированы как однобайтовые последовательности в UTF-8, так что да, простая лямбда работает для UTF-8.
добавлено автор R. Martinho Fernandes, источник
Мои извинения. Я немного запутался в истинном характере проблемы :) Я знал, что использование isspace было неправильным, но я смутился о том, почему. Почему это связано с isspace с использованием int и char . Вот небольшая программа, которая объясняет проблему stacked-crooked.com/view?id=817f92f4a2482e5da0b7533285e53edb</а> & ZWNJ;.
добавлено автор R. Martinho Fernandes, источник
Неважно, я был совершенно глупым и не передавал второй аргумент erase (я набрал один до ответа).
добавлено автор chris, источник
@CashCow, я знаю, это совершенно раздражает, когда вы его забываете. В моем случае я никогда не видел второго аргумента, когда читал его, сколько раз, прежде чем я, наконец, использовал его, так что он по-прежнему подключен в моем мозгу, что он принимает только один.
добавлено автор chris, источник
@chris :: isspace включает также новую строку: cplusplus. ком/ссылки/cctype/isspace
добавлено автор Ivaylo Strandjev, источник
Хорошо, я дал альтернативный ответ, который использует std :: isspace с языковой версией.
добавлено автор CashCow, источник
Вы говорите, что то, что выглядит как пробел, никогда не будет отображаться как часть многобайтового символа? Я не знаю стандарта UTF-8. Единственное, что я вижу как «неопределенное», это такие вещи, как & nbsp; (неразрывное пространство), которое обычно является ASCII 160 (или 0xA0), но может варьироваться в других наборах символов.
добавлено автор CashCow, источник
Предположительно -1 из г-на Фернандеса для использования :: isspace. возможно, он просветит нас в отношении специальной языковой основы/набора символов? Вы знаете, что для идеального UTF-8 это не обязательно даже отношение персонажа к персонажу, поэтому функтор/лямбда здесь не будут работать официально. Единственное, что будет работать для идеальной итерации UTF-8, которая может быть многосимвольной, - это пользовательский итератор.
добавлено автор CashCow, источник
@chris Да, поскольку std :: remove_if возвращает итератор, и erase имеет перегрузку для одного итератора, он действительно скомпилирует и не даст вам результат, который вы хотите, если забудете второй s.end ()
добавлено автор CashCow, источник
@ R.MartinhoFernandes ли стандарт C99 применяется к C ++? C ++ имеет свой собственный стандарт.
добавлено автор CashCow, источник
Как вы выполнили свою работу? Вы уверены, что не вставили его, например, (std :: cout << s << std :: endl)
добавлено автор CashCow, источник
это будет. isspace вернет true для строк новой строки.
добавлено автор CashCow, источник
Не требуется ли для лямбда-версии утверждение «возврат»?
добавлено автор PatchyFog, источник
Для новичков C ++, подобных мне _1, из std :: placeholders и представляют будущие аргументы
добавлено автор bmatovu, источник

Если C ++ 03

struct RemoveDelimiter
{
  bool operator()(char c)
  {
    return (c =='\r' || c =='\t' || c == ' ' || c == '\n');
  }
};

std::string s("\t\tHELLO WORLD\r\nHELLO\t\nWORLD     \t");
s.erase( std::remove_if( s.begin(), s.end(), RemoveDelimiter()), s.end());

Или используйте C ++ 11 лямбда

s.erase(std::remove_if( s.begin(), s.end(), 
     [](char c){ return (c =='\r' || c =='\t' || c == ' ' || c == '\n');}), s.end() );

PS. Исключить удаление идиомы

12
добавлено

В C ++ 11 вы можете использовать лямбда, а не использовать std :: bind:

str.erase(
    std::remove_if(str.begin(), str.end(), 
        [](char c) -> bool
        { 
            return std::isspace(c, std::locale::classic()); 
        }), 
    str.end());
3
добавлено

You could use Boost.Algorithm's erase_all

#include 
#include 
#include 

int main()
{
    std::string s = "Hello World!";
   //or the more expensive one-liner in case your string is const
   //std::cout << boost::algorithm::erase_all_copy(s, " ") << "\n";
    boost::algorithm::erase_all(s, " "); 
    std::cout << s << "\n";
}

ПРИМЕЧАНИЕ: как указано в комментариях: trim_copy (или его кузены trim_copy_left и trim_copy_right )) удаляют только пробелы с начала и конца строки ,

2
добавлено
Я видел некоторые решения, которые использовали Boost, но я не после функции trim , обрезка, я считаю, делает что-то вроде XX ___ XX _ -> XX_XX тогда как я хочу, чтобы окончательное решение было XXXX .
добавлено автор Mr. Smith, источник
@ Mr.Smith Tnx, обновлено.
добавлено автор TemplateRex, источник

C ++ 11

std::string input = "\t\tHELLO WORLD\r\nHELLO\t\nWORLD     \t";

auto rs = std::regex_replace(input,std::regex("\\s+"), "");

std::cout << rs << std::endl;

/tmp ❮❮❮ ./play

HELLOWORLDHELLOWORLD
2
добавлено

Пройдя через него символ по символу и используя string :: erase() должен работать нормально.

void removeWhitespace(std::string& str) {
    for (size_t i = 0; i < str.length(); i++) {
        if (str[i] == ' ' || str[i] == '\n' || str[i] == '\t') {
            str.erase(i, 1);
            i--;
        }
    }
}
1
добавлено
Не работает, когда есть смежные пробелы. Первый из них стирается, перемещая второй до положения i . Затем вы обходите цикл, увеличиваете i и никогда не проверяете второй.
добавлено автор Steve Jessop, источник
Ты прав. Починил это.
добавлено автор SelectricSimian, источник
pro.cxx
pro.cxx
3 049 участник(ов)

C/C++ chat 0. Простые вопросы, лабы и о IDE — в чат новичков @supapro 1. Не хамим, не переходим на личности, не вбрасываем утверждения без доказательств 2. No Ads, offtop, flood Объявления о вакансиях и евенты - в лс @AlexFails https://t.me/ProCxx/259155

supapro.cxx
supapro.cxx
1 925 участник(ов)

Чат для тех, кто немного знает C++, простые вопросы по реализации, синтаксису и ide – сюда, а для другого есть: /Главный чат по серьезным вопросам — @ProCxx /Чат по обсуждению всего — @fludpac

C++ Russia
C++ Russia
384 участник(ов)

Сообщество разработчиков C++ в Telegram.

cxx.Дискуссионная
cxx.Дискуссионная
298 участник(ов)

это не двач, общайтесь вежливо; разговор на почти любые темы; Не согласны с баном? В лс @AlexFails, @ivario

C++ для маленьких и тупых
C++ для маленьких и тупых
105 участник(ов)

Лоу левел (по среднему IQ участников) чатик ExtremeCode @extremecode Флудилка @extremecode_rest