Как бы я сделал что-то вроде этого (java) string.replaceAll(" ", " ")
в С++
это сделало бы так, чтобы все множественные пробелы становились всего одним.
Как бы я сделал что-то вроде этого (java) string.replaceAll(" ", " ")
в С++
это сделало бы так, чтобы все множественные пробелы становились всего одним.
bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }
std::string::iterator new_end = std::unique(str.begin(), str.end(), BothAreSpaces);
str.erase(new_end, str.end());
Как это работает. std::unique
имеет две формы. Первая форма проходит через диапазон и удаляет соседние дубликаты. Итак, строка "abbaaabbbb" становится "abab". Вторая форма, которую я использовал, принимает предикат, который должен принимать два элемента и возвращать true, если их следует считать дублирующими. Функция, которую я написал, BothAreSpaces
, служит этой цели. Он точно определяет, что означает это имя, что оба параметра - это пробелы. Поэтому в сочетании с std::unique
дублируются смежные пространства.
Также как std::remove
и remove_if
, std::unique
фактически не делает контейнер меньшим, он просто перемещает элементы ближе к началу. Он возвращает итератор в новый конец диапазона, поэтому вы можете использовать его для вызова функции erase
, которая является функцией-членом функции Строковый класс.
Разбивая его, функция стирания принимает два параметра: начальный и конечный итератор для диапазона для стирания. Для него первый параметр я передает возвращаемое значение std::unique
, потому что там, где я хочу начать стирание. Для этого второго параметра я передаю итератор конца строки.
Итак, я пробовал путь с std:: remove_if и лямбда-выражениями - хотя мне кажется, что мне все еще легче смотреть, чем над кодом, у него нет "ничего себе", не понимал, что вы можете это сделать "вещь к этому.. В любом случае я все равно размещаю его, если только для учебных целей:
bool prev(false);
char rem(' ');
auto iter = std::remove_if(str.begin(), str.end(), [&] (char c) -> bool {
if (c == rem && prev) {
return true;
}
prev = (c == rem);
return false;
});
in.erase(iter, in.end());
EDIT понял, что std:: remove_if возвращает итератор, который можно использовать.. удаленный ненужный код.
Вариант ответа Бенджамина Линдли, который использует выражение лямбда, чтобы сделать вещи чище:
std::string::iterator new_end =
std::unique(str.begin(), str.end(),
[=](char lhs, char rhs){ return (lhs == rhs) && (lhs == ' '); }
);
str.erase(new_end, str.end());
Почему бы не использовать регулярное выражение:
boost::regex_replace(str, boost::regex("[' ']{2,}"), " ");
как насчет isspace(lhs) && isspace(rhs)
для обработки всех типов пробелов