Страницы

Поиск по вопросам

четверг, 19 декабря 2019 г.

Убрать лишние пробелы и табы в std::string строке

#cpp #строки


Допустим есть строка с именем процессора, которую возвращает функция GetProcessorName():

// "Intel Core2 Duo  CPU    P8400  @ 2.26GHz"
std::string some_string = GetProcessorName();


Необходимо убрать лишние пробелы. То есть, отформатировать строку так, чтобы между
словами не было лишних пробелов или знаков табуляции. Вот так:

// "Intel Core2 Duo CPU P8400 @ 2.26GHz";


Пробовал replace & replace_if, в конце-концов понял, что эти и подобные им алгоритмы
предназначены исключительно для контейнеров. Возможно лямбды помогут. Что посоветуете
делать с std::string?
    


Ответы

Ответ 1



вообще то std::string - это обычный контейнер. такой же, как обычный std::vector. Если не хочется remove/remove_if и душа требует лямбд, можно так #include #include #include using namespace std; int main() { std::string some_string = "Intel Core2 Duo CPU P8400 @ 2.26GHz"; auto end = std::unique(some_string.begin(), some_string.end(), [](char l, char r){ return std::isspace(l) && std::isspace(r) && l == r; }); std::cout << std::string(some_string.begin(), end) << '\n'; return 0; } UPD Некоторые предлагают переписать условие std::isspace(l) && std::isspace(r) && l == r как std::isspace(l) && l == r я бы его все таки переписал как std::isspace(l) && std::isspace(r) Почему? В вопросе звучит "удалить лишние пробелы и табы". А если строка такая (символ подчеркивания - это пробел, а \t - табуляция) a\t\t__\t_\tb то ее наверно правильно было бы сократить до a_b, а не a\t_\t_\tb. Но если посмотреть, что именно проверяет std::isspace, то узнаете, что перевод строки (\n) также считается. Поэтому, если строка будет многострочной вида abc_\n_def, то она будет сокращена до abc_def, что может быть не совсем то, что хочется. Кстати, это вариант ближе к варианту с регуляркой в ответе @GreenDragon, так как \s работает как isspace.

Ответ 2



Ну а чем string не контейнер? :) Сами убедитесь: int main(int argc, const char * argv[]) { string s = "Intel Core2 Duo CPU P8400 @ 2.26GHz"; s = s.substr(0,distance(s.begin(),remove_if(s.begin(), s.end(), [](const char& a) { return (a == ' ') && (*(&a+1) == ' '); }))); cout << "[" << s << "]\n"; }

Ответ 3



Для работы с текстом можно использовать регулярные выражения. Начиная с C++11 в стандартной библиотеке появилась их поддержка, поэтому вашу задачу также можно решить следующим способом: #include #include #include int main() { std::string str= "Intel Core2 Duo CPU P8400 @ 2.26GHz"; std::regex e("(\\s)+"); std::cout << std::regex_replace (str,e,"$1")<<"\n"; }

Ответ 4



Немного упрощенный вариант кода @KoVadim под c++03: #include #include #include #include bool space2(char l, char r) { return l == r && std::isspace(l); } int main() { std::string s = "Intel Core2 Duo CPU P8400 @ 2.26GHz"; std::cout << std::string(s.begin(), std::unique(s.begin(), s.end(), space2)) << '\n'; }

Комментариев нет:

Отправить комментарий