Как обрезать пробелы в начале и конце std::string в C++?
Решение: обрезка строки с помощью STL
В стандартной библиотеке C++ нет встроенного метода trim для std::string, но его легко реализовать с помощью алгоритмов из STL. Вот наиболее эффективный и правильный способ:
#include <string>
#include <algorithm>
#include <cctype>
// Обрезка пробелов в начале
std::string ltrim(const std::string& s) {
auto it = std::find_if_not(s.begin(), s.end(),
[](unsigned char ch) { return std::isspace(ch); });
return std::string(it, s.end());
}
// Обрезка пробелов в конце
std::string rtrim(const std::string& s) {
auto it = std::find_if_not(s.rbegin(), s.rend(),
[](unsigned char ch) { return std::isspace(ch); });
return std::string(s.begin(), it.base());
}
// Полная обрезка
std::string trim(const std::string& s) {
return ltrim(rtrim(s));
}
Как это работает
- std::isspace — функция из <cctype>, которая проверяет, является ли символ пробельным (пробел, табуляция, перевод строки и т.д.). Важно использовать
unsigned charдля избежания проблем с отрицательными символами. - std::find_if_not — находит первый элемент, не удовлетворяющий условию. Для ltrim ищем слева направо, для rtrim — справа налево (через обратные итераторы).
- it.base() — преобразует обратный итератор в обычный для корректного конструирования строки.
- Функции возвращают новую строку, не изменяя исходную (работает по значению).
Альтернативный вариант: модификация на месте
Если нужно изменить существующую строку без копирования:
void trim_in_place(std::string& s) {
// Удаляем пробелы в конце
s.erase(std::find_if_not(s.rbegin(), s.rend(),
[](unsigned char ch) { return std::isspace(ch); }).base(), s.end());
// Удаляем пробелы в начале
s.erase(s.begin(), std::find_if_not(s.begin(), s.end(),
[](unsigned char ch) { return std::isspace(ch); }));
}
Пример использования
#include <iostream>
int main() {
std::string str = " \t Hello, World! \n ";
std::cout << "Исходная: \"" << str << "\"\n";
std::cout << "Обрезанная: \"" << trim(str) << "\"\n";
// Вывод: Обрезанная: "Hello, World!"
trim_in_place(str);
std::cout << "После trim_in_place: \"" << str << "\"\n";
return 0;
}
Важные замечания
- Функция
std::isspaceобрабатывает все стандартные пробельные символы: ' ', '\t', '\n', '\r', '\f', '\v'. - Если строка состоит только из пробелов, обе версии вернут пустую строку.
- Для C++17 и новее можно использовать
std::string_viewдля избежания копирования при передаче строк. - Если вы используете Boost, там есть готовая функция
boost::trim, но решение на STL не требует внешних зависимостей.
Этот подход эффективен (линейная сложность O(n)), корректен для всех пробельных символов и следует идиоматическому стилю C++.
<<Решение с помощью std::regex (C++11 и новее)
Можно использовать регулярные выражения для обрезки строки. Этот способ более декларативный, но может быть медленнее для больших строк:
#include <string>
#include <regex>
std::string trim_regex(const std::string& s) {
static const std::regex pattern(R"(^\s+|\s+$)"); // Убираем пробелы в начале и конце
return std::regex_replace(s, pattern, "");
}
Пример:
std::string str = " \t Example text \n ";
std::cout << trim_regex(str); // Вывод: "Example text"
Плюсы и минусы
- Плюсы: короткий код, легко читается, можно легко модифицировать для других паттернов (например, удаление только пробелов, а не всех whitespace).
- Минусы: производительность ниже (регулярные выражения компилируются и исполняются медленнее ручного поиска), подходит только для строк, где производительность не критична.
Если вы пишете код для учебных целей или обработки единичных строк — этот вариант вполне подойдет. Для высоконагруженных приложений лучше использовать первый ответ с STL.