В настоящее время я использую следующий код, чтобы урезать все std::strings
мои программы вправо :
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Это работает нормально, но мне интересно, есть ли какие-то конечные случаи, когда он может потерпеть неудачу?
Конечно, приветствуются ответы с элегантными альтернативами, а также левостороннее решение.
std::string
класс, когда именно такие функции делают использование других языков таким приятным (например, Python).Ответы:
РЕДАКТИРОВАТЬ Начиная с c ++ 17, некоторые части стандартной библиотеки были удалены. К счастью, начиная с c ++ 11, у нас есть лямбды, которые являются превосходным решением.
Спасибо https://stackoverflow.com/a/44973498/524503 за предоставление современного решения.
Оригинальный ответ:
Я склонен использовать один из этих 3 для моих нужд обрезки:
Они достаточно понятны и работают очень хорошо.
РЕДАКТИРОВАТЬ : Кстати, я
std::ptr_fun
там, чтобы помочь устранить неоднозначность,std::isspace
потому что на самом деле есть второе определение, которое поддерживает локали. Это мог бы быть актерский состав точно так же, но мне это нравится больше.РЕДАКТИРОВАТЬ : Чтобы ответить на некоторые комментарии о принятии параметра по ссылке, его изменения и возврата. Согласен. Я бы предпочел реализацию, состоящую из двух наборов функций: одну на месте и одну, которая делает копию. Лучшим набором примеров будет:
Я сохраняю первоначальный ответ выше, хотя для контекста и в интересах сохранения высокого ответа по-прежнему доступны.
источник
boost::trim
для решения проблемы.Использовать строковые алгоритмы Boost было бы проще всего:
str
в настоящее время"hello world!"
. Там такжеtrim_left
иtrim
, который уравновешивает обе стороны.Если вы добавите
_copy
суффикс к какому-либо из названий функций, напримерtrim_copy
, функция вернет обрезанную копию строки вместо того, чтобы изменять ее через ссылку.Если вы добавите
_if
суффикс к какому-либо из названий функций, напримерtrim_copy_if
, вы можете обрезать все символы, удовлетворяющие вашему пользовательскому предикату, а не только пробелам.источник
Используйте следующий код для выравнивания (конечных) пробелов и символов табуляции от
std::strings
( ideone ):И просто, чтобы уравновесить ситуацию, я также включу левый код обрезки ( ideone ):
источник
str.substr(...).swap(str)
лучше. Сохраните назначение.basic_string& operator= (basic_string&& str) noexcept;
?То, что вы делаете, прекрасно и надежно. Я использовал один и тот же метод в течение длительного времени, и мне еще предстоит найти более быстрый метод:
Предоставляя обрезаемые символы, вы можете обрезать непробельные символы и эффективно обрезать только те символы, которые хотите обрезать.
источник
trim
, т.е. сделаете его,rtrim(ltrim(s, t), t)
он будет немного более эффективнымНемного опоздал на вечеринку, но не бери в голову. Теперь C ++ 11 здесь, у нас есть лямбды и авто переменные. Итак, моя версия, которая также обрабатывает все пробелы и пустые строки:
Мы могли бы сделать обратный итератор
wsfront
и использовать его в качестве условия завершения во второмfind_if_not
но это полезно только в случае строки со всеми пробелами, и gcc 4.8 по крайней мере недостаточно умен, чтобы вывести тип обратного итератора (std::string::const_reverse_iterator
) сauto
. Я не знаю, насколько дорогой является создание обратного итератора, так что YMMV здесь. С этим изменением код выглядит так:источник
std::isspace
:auto wsfront=std::find_if_not(s.begin(),s.end(),std::isspace);
candidate template ignored: couldn't infer template argument '_Predicate' find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred)
Попробуйте это, это работает для меня.
источник
str.find_last_not_of(x)
возвращает позицию первого символа, не равного x. Он возвращает npos только если никакие символы не совпадают с x. В примере, если нет пробелов с суффиксами, он вернет эквивалентstr.length() - 1
, по сути,str.erase((str.length() - 1) + 1).
то есть, если я не ошибаюсь.std::string&
.Мне нравится решение Цамана, единственная проблема в том, что оно не обрезает строку, содержащую только пробелы.
Чтобы исправить этот 1 недостаток, добавьте str.clear () между двумя линиями триммера
источник
ltrim
илиrtrim
как это.std::stringstream
.http://ideone.com/nFVtEo
источник
it
) и наоборот: позиция символа, после которой есть только пробелы (rit
) - после этого она возвращает вновь созданную строку == копия части исходной строки - части, основанной на этих итераторах ...В случае пустой строки ваш код предполагает, что добавление 1 к
string::npos
дает 0.string::npos
имеет типstring::size_type
, который без знака. Таким образом, вы полагаетесь на поведение переполнения сложения.источник
1
кstd::string::npos
должны дать в0
соответствии сC++ Standard
. Так что это хорошее предположение, на которое можно абсолютно положиться.Отрублены из Cplusplus.com
Это работает и для нулевого случая. :-)
источник
rtrim
, нетltrim
В C ++ 17 вы можете использовать basic_string_view :: remove_prefix и basic_string_view :: remove_suffix :
Хорошая альтернатива:
источник
Мое решение основано на ответе @Bill the Lizard .
Обратите внимание, что эти функции будут возвращать пустую строку, если входная строка не содержит ничего, кроме пробела.
источник
Мой ответ - это улучшение верхнего ответа на этот пост, который урезает управляющие символы, а также пробелы (0-32 и 127 в таблице ASCII ).
std::isgraph
определяет, имеет ли символ графическое представление, так что вы можете использовать это, чтобы изменить ответ Эвана, чтобы удалить любой символ, который не имеет графического представления с любой стороны строки. В результате получается гораздо более элегантное решение:Примечание. В качестве альтернативы вы можете использовать ее,
std::iswgraph
если вам нужна поддержка широких символов, но вам также придется отредактировать этот код, чтобы включитьstd::wstring
манипуляции, что я не проверял (см. Страницу справки дляstd::basic_string
изучения этой опции) ,источник
С C ++ 11 также появился модуль регулярных выражений , который, конечно, можно использовать для обрезания начальных или конечных пробелов.
Может быть, что-то вроде этого:
источник
Это то, что я использую. Просто продолжайте убирать пространство спереди, а затем, если что-то осталось, сделайте то же самое сзади.
источник
источник
Для чего это стоит, вот аккуратная реализация с оглядкой на производительность. Это намного быстрее, чем многие другие процедуры обрезки, которые я видел вокруг. Вместо использования итераторов и std :: find он использует необработанные строки и индексы c. Он оптимизирует следующие особые случаи: строка размера 0 (ничего не делать), строка без пробелов для обрезки (ничего не делать), строка только с последующим пробелом для обрезки (просто изменить размер строки), строка, которая полностью пуста (просто очистить строку) , И, наконец, в худшем случае (строка с начальным пробелом), она делает все возможное, чтобы создать эффективную копию, выполнив только 1 копию, а затем переместив эту копию вместо исходной строки.
источник
Элегантный способ сделать это может быть как
И поддерживающие функции реализованы так:
И как только вы все это на месте, вы также можете написать это:
источник
Trim C ++ 11 реализация:
источник
Я предполагаю, что если вы начнете спрашивать «лучший способ» обрезать строку, я бы сказал, что хорошей реализацией будет та, которая:
Очевидно, что существует слишком много разных способов приблизиться к этому, и это определенно зависит от того, что вам действительно нужно. Однако в стандартной библиотеке C все еще есть несколько очень полезных функций в <string.h>, таких как memchr. Есть причина, почему C по-прежнему считается лучшим языком для ввода-вывода - его стандартная эффективность - чистая эффективность.
источник
Я не уверен, что ваша среда такая же, но в моем случае случай с пустой строкой приведет к прерыванию работы программы. Я бы либо обернул этот вызов стирания с помощью if (! S.empty ()), либо использовал Boost, как уже упоминалось.
источник
Вот что я придумал:
Извлечение потока автоматически удаляет пробелы, поэтому это работает как шарм.
Довольно чистый и элегантный, если я так скажу. ;)
источник
Вклад моего решения в шум.
trim
по умолчанию создает новую строку и возвращает измененную, аtrim_in_place
изменяет переданную ей строку. Вtrim
функции поддерживает C ++ 11 хода семантики.источник
Это можно сделать проще в C ++ 11 за счет добавления
back()
иpop_back()
.источник
Вот моя версия:
источник
Вышеуказанные методы хороши, но иногда вы хотите использовать комбинацию функций для того, что ваша подпрограмма считает пробелом. В этом случае использование функторов для объединения операций может стать беспорядочным, поэтому я предпочитаю простой цикл, который можно изменить для обрезки. Вот слегка измененная функция обрезки, скопированная с версии C здесь, на SO. В этом примере я обрезаю не буквенно-цифровые символы.
источник
Вот прямая реализация. Для такой простой операции вам, вероятно, не следует использовать какие-либо специальные конструкции. Встроенная функция isspace () заботится о различных формах белых символов, поэтому мы должны воспользоваться этим. Вы также должны рассмотреть особые случаи, когда строка пуста или просто группа пробелов. Обрезка влево или вправо может быть получена из следующего кода.
источник
Вот решение, простое для понимания новичками, которые не привыкли писать
std::
везде и еще не знакомы сconst
-корректностью,iterator
s, STLalgorithm
и т. Д.Надеюсь, поможет...
источник
Эта версия урезает внутренние пробелы и не алфавитно-цифровые:
источник
Еще один вариант - удаляет один или несколько символов с обоих концов.
источник