Как обрезать std::string?
Я в данный момент использую следующий код для удаления пробелов и символов новой строки с правой стороны всех std::string
в своих программах:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Этот подход работает хорошо, но мне интересно, есть ли некоторые крайние случаи, в которых он может не сработать?
Разумеется, я буду рад любым ответам с элегантными альтернативами, а также решениям для удаления пробелов с левой стороны строки.
5 ответ(ов)
Ваш подход вполне корректен и надежен. Я также долго использовал этот метод и пока не нашел более быстрого способа.
Ваш код выглядит следующим образом:
const char* ws = " \t\n\r\f\v";
// удаление пробелов с конца строки (право)
inline std::string& rtrim(std::string& s, const char* t = ws)
{
s.erase(s.find_last_not_of(t) + 1);
return s;
}
// удаление пробелов в начале строки (лево)
inline std::string& ltrim(std::string& s, const char* t = ws)
{
s.erase(0, s.find_first_not_of(t));
return s;
}
// удаление пробелов с обоих концов строки (сначала право, затем лево)
inline std::string& trim(std::string& s, const char* t = ws)
{
return ltrim(rtrim(s, t), t);
}
Предоставляя символы для обрезки, вы получаете гибкость в удалении не только символов пробела, но и эффективность, позволяя обрезать только те символы, которые вы хотите удалить.
Мне нравится решение, предложенное tzaman, но единственная проблема в том, что оно не удаляет пробелы из строки, содержащей только пробелы.
Чтобы исправить этот недостаток, добавьте вызов str.clear()
между двумя линиями, отвечающими за обрезку:
std::stringstream trimmer;
trimmer << str;
str.clear();
trimmer >> str;
Таким образом, если строка состоит только из пробелов, она будет успешно очищена.
В случае пустой строки ваш код предполагает, что добавление 1 к string::npos
дает 0. Однако string::npos
имеет тип string::size_type
, который является беззнаковым. Таким образом, вы полагаетесь на поведение переполнения при сложении.
Попробуйте этот код, он работает для меня:
inline std::string trim(std::string& str)
{
str.erase(str.find_last_not_of(' ') + 1); // удаление пробелов в конце
str.erase(0, str.find_first_not_of(' ')); // удаление пробелов в начале
return str;
}
Этот метод удаляет пробелы в начале и конце строки.
Ваша функция trim
, написанная на C++, предназначена для удаления пробелов из начала и конца строки. Давайте разберем, как она работает, и я помогу перевести этот код на русский язык.
Вот ваш оригинальный код:
std::string trim(const std::string &s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && isspace(*it))
it++;
std::string::const_reverse_iterator rit = s.rbegin();
while (rit.base() != it && isspace(*rit))
rit++;
return std::string(it, rit.base());
}
Функция использует два итератора: один для начала строки (прямой итератор it
), а другой для конца строки (обратный итератор rit
). Сначала она перемещает прямой итератор до первого ненормированного символа, пропуская все пробелы в начале строки. Затем она использует обратный итератор, чтобы опуститься до первого ненормированного символа с конца строки, пропуская пробелы в конце. Наконец, она возвращает новую строку, которая начинается с it
и заканчивается перед rit.base()
.
Вот перевод вашей функции trim
на русский:
std::string обрезать(const std::string &s)
{
std::string::const_iterator ит = s.begin();
while (ит != s.end() && isspace(*ит))
ит++;
std::string::const_reverse_iterator рит = s.rbegin();
while (рит.base() != ит && isspace(*рит))
рит++;
return std::string(ит, рит.base());
}
Также, если вам нужно короткое объяснение по поводу использования этой функции, вы можете добавить следующее:
Описание:
Эта функция удаляет пробелы из начала и конца заданной строки. Вы можете использовать обрезать(s)
для получения строки без начальных и конечных пробелов.
Как преобразовать std::string в const char* или char*
Когда использовать виртуальные деструкторы?
Какова разница между 'typedef' и 'using'?
Циклы в программном обеспечении для семейных деревьев
Что означает 'const' в конце объявления метода класса?