Заменить несколько пробелов одним пробелом в строке - PullRequest
21 голосов
/ 03 декабря 2011

Как бы я сделал что-то в c++, похожее на следующий код:

//Lang: Java
string.replaceAll("  ", " ");

Этот фрагмент кода заменит все несколько пробелов в строке одним пробелом.

Ответы [ 5 ]

63 голосов
/ 03 декабря 2011
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, потому что именно здесь я хочу начать стирание.Для второго параметра я передаю итератор конца строки.

4 голосов
/ 03 декабря 2011

Итак, я попробовал способ с выражениями std:: "вещь к этому .. В любом случае я все еще отправляю это, хотя бы для учебных целей:

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());

РЕДАКТИРОВАТЬ понял, что std :: remove_if возвращает итератор, который может быть использован .. удалены ненужный код.

3 голосов
/ 03 сентября 2016

Вариант ответа Бенджамина Линдли, который использует лямбда-выражение, чтобы сделать вещи чище:

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());
1 голос
/ 21 февраля 2015

Почему бы не использовать регулярное выражение:

boost::regex_replace(str, boost::regex("[' ']{2,}"), " ");

0 голосов
/ 05 октября 2017

как насчет isspace(lhs) && isspace(rhs) для обработки всех типов пробелов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...