Обрезка внутренних пробелов в std :: string - PullRequest
5 голосов
/ 19 февраля 2012

Я ищу элегантный способ преобразования std :: string из чего-то вроде:

std::string text = "   a\t   very  \t   ugly   \t\t\t\t   string       ";

Кому:

std::string text = "a very ugly string";

Я уже обрезал внешний пробел с помощью boost::trim(text);

[править] Таким образом, несколько пробелов и табуляции уменьшаются до одного пробела [/ Править]

Удаление внешнего пробела тривиально. Но существует ли элегантный способ удаления внутреннего пробела, который не требует ручной итерации и сравнения предыдущих и следующих символов? Возможно, что-то в boost я пропустил?

Ответы [ 6 ]

7 голосов
/ 19 февраля 2012
std::istringstream iss(text);
text = "";
std::string s;
while(iss >> s){
     if ( text != "" ) text += " " + s;
     else text = s;
}
//use text, extra whitespaces are removed from it
7 голосов
/ 19 февраля 2012

Вы можете использовать std::unique с std::remove и ::isspace для сжатия нескольких пробельных символов в один пробел:

std::remove(std::unique(std::begin(text), std::end(text), [](char c, char c2) {
    return ::isspace(c) && ::isspace(c2);
}), std::end(text));
4 голосов
/ 19 февраля 2012

Большая часть того, что я сделал бы, похожа на то, что @Nawaz уже опубликовал - читает строки из istringstream, чтобы получить данные без пробелов, а затем вставляет один пробел между каждой из этих строк. Тем не менее, я бы использовал infix_ostream_iterator из предыдущего ответа , чтобы получить (ИМО) немного чище / яснее код.

std::istringstream buffer(input);

std::copy(std::istream_iterator<std::string>(buffer),
          std::istream_iterator<std::string>(),
          infix_ostream_iterator<std::string>(result, " "));
3 голосов
/ 08 апреля 2014
#include <boost/algorithm/string/trim_all.hpp>
string s;
boost::algorithm::trim_all(s);
1 голос
/ 19 февраля 2012

Если вы посмотрите https://svn.boost.org/trac/boost/ticket/1808,, вы увидите запрос (почти) этой точной функциональности и предлагаемую реализацию:

std::string trim_all ( const std::string &str ) {
return boost::algorithm::find_format_all_copy(
    boost::trim_copy(str),
    boost::algorithm::token_finder (boost::is_space(),boost::algorithm::token_compress_on),
    boost::algorithm::const_formatter(" "));
}
0 голосов
/ 20 февраля 2012

Вот возможная версия с использованием регулярных выражений.Мой GCC 4.6 еще не имеет regex_replace, но Boost.Regex может служить заменой для вставки:

#include <string>
#include <iostream>
// #include <regex>
#include <boost/regex.hpp>
#include <boost/algorithm/string/trim.hpp>

int main() {
  using namespace std;
  using namespace boost;
  string text = "   a\t   very  \t   ugly   \t\t\t\t   string       ";
  trim(text);
  regex pattern{"[[:space:]]+", regex_constants::egrep};
  string result = regex_replace(text, pattern, " ");
  cout << result << endl;
}
...