C++ 修剪std::string中的内部空白

C++ 修剪std::string中的内部空白,c++,string,boost,stl,trim,C++,String,Boost,Stl,Trim,我正在寻找一种优雅的方法来将std::string从以下内容转换为: std::string text = " a\t very \t ugly \t\t\t\t string "; 致: 我已经用boost::trim(text)修剪了外部空白 [编辑] 因此,多个空格和制表符被缩减为一个空格 [/编辑] 删除外部空白并不重要。但是,有没有一种优雅的方法可以消除内部空白,而不需要手动迭代和比较上一个字符和下一个字符?也许我错过了boost中的某些内容?您可以

我正在寻找一种优雅的方法来将std::string从以下内容转换为:

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

我已经用
boost::trim(text)修剪了外部空白

[编辑] 因此,多个空格和制表符被缩减为一个空格 [/编辑]


删除外部空白并不重要。但是,有没有一种优雅的方法可以消除内部空白,而不需要手动迭代和比较上一个字符和下一个字符?也许我错过了
boost
中的某些内容?

您可以将
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));

我要做的大部分工作与@Nawaz已经发布的内容类似——从
istringstream
读取字符串,以获取不带空格的数据,然后在每个字符串之间插入一个空格。然而,我会使用来自a的
infix\u ostream\u迭代器
,以获得(IMO)稍微干净/清晰的代码

std::istringstream buffer(input);

std::copy(std::istream_iterator<std::string>(buffer),
          std::istream_iterator<std::string>(),
          infix_ostream_iterator<std::string>(result, " "));
std::istringstream缓冲区(输入);
std::copy(std::istream_迭代器(缓冲区),
std::istream_迭代器(),
中缀ostream迭代器(结果“”);
如果您签出,您将看到(几乎)此确切功能的请求,以及建议的实现:

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

下面是一个使用正则表达式的可能版本。我的GCC4.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;
}
#包括
#包括
//#包括
#包括
#包括
int main(){
使用名称空间std;
使用名称空间boost;
string text=“a\t非常\t丑陋\t\t\t\t字符串”;
修剪(文本);
正则表达式模式{“[:space:][]+”,正则表达式常量::egrep};
字符串结果=regex_replace(文本,模式,“”);
不能包含
字符串s;
boost::algorithm::trim_all(s);

它不会解决他的问题。
测试
也包含
'\t'
,它不等于
'
。这不也会做“让”->“让”这样的事情吗然后跳过“\t`pairs”?哎哟,再次修复了它,以前它不会合并,例如,一个空格和一个制表符,但现在它合并了。这不会导致示例输入的
“一个非常难看的字符串”
,这是错误的吗?您可以添加一个
转换过程(或者可能是
boost::transform\u迭代器
)用空格字符替换所有空格,但有时可以放弃并编写循环;-)为什么
std::remove
?您需要
std::replace_if
std::unique
之后用
'
替换
\t
字符,它仍然不会删除前导和尾随的空格。这个答案并不正确按照OP的要求去做。啊,有趣的方法,+1,尽管我不知道你我之间哪一种效率更高(或者它对小字符串或代码的“冷”区域更重要),我认为,在else块中
text.append(“+s”);
会快一点。这不会做同样的事情?(现在它用
操作符=
覆盖了以前的内容,但是
附加
就像将其更改为
+=
;我认为这可能是原始代码中的一个输入错误)@SethCarnegie:但这正是我们想要的。对不起,它应该是
+=
,而不是
+
。我不知道为什么人们在它不完全正确的时候投票了:作为一个迂腐的注释,如果(!text.empty())做
,可能比
如果(text!=”)做得更好
请注意,我并没有真正使用过
boost::split
boost::join
,但是用Python编写这篇文章的明显方法是
''.join(text.split())
,类似的方法应该是可能的。它不一定像将字节直接复制到其最终位置那样高效,但它简洁明了。是的;如果您不介意复制,拆分和合并效果会很好;如果您担心效率(在本例中),编写自己的循环可能是最好的。@Marshall:我的工作是基于问题是“优雅”,而不是“快速但丑陋”;-)尝试添加代码块,但没有运气..添加答案,但我认为这是正确的方向。
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(" "));
}
#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;
}
#include <boost/algorithm/string/trim_all.hpp>
string s;
boost::algorithm::trim_all(s);