【问题标题】:Trimming internal whitespace in std::string修剪 std::string 中的内部空格
【发布时间】:2012-02-19 16:21:32
【问题描述】:

我正在寻找一种优雅的方式来将 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 中的某些内容?

【问题讨论】:

  • 请注意,我并没有真正使用过boost::splitboost::join,但是用Python 编写它的明显方法是' '.join(text.split()),类似的东西应该是可能的。它不一定像将字节直接复制到最终位置那样高效,但它简洁明了。
  • 是的;如果您不介意复制,拆分和加入效果很好;如果您担心效率(在这种情况下),编写自己的循环可能是最好的。
  • @Marshall:我的工作是基于问题所说的“优雅”,而不是“快速但丑陋”;-)

标签: c++ string boost stl trim


【解决方案1】:

您可以使用std::uniquestd::remove 以及::isspace 将多个空白字符压缩为单个空格:

std::remove(std::unique(std::begin(text), std::end(text), [](char c, char c2) {
    return ::isspace(c) && ::isspace(c2);
}), std::end(text));

【讨论】:

  • 解决不了他的问题。 test 还包含不等于 ' ''\t'
  • 这不会也做“letting”->“leting”之类的事情并跳过`\t`对吗?
  • 哎呀再次修复它,以前它不会组合,例如,一个空格和一个标签彼此相邻,但现在它可以了。
  • 这不会导致样本输入为"a\tvery ugly string",这是错误的吗?你可以添加一个transform(或者boost::transform_iterator?)来用空格字符替换所有空格,但有时可以放弃并编写一个循环;-)
  • 为什么是std::remove?您需要在std::unique 之后使用std::replace_if\t 字符替换为' ',它仍然不会删除前导和尾随空格。这个答案不符合 OP 的要求。
【解决方案2】:
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

【讨论】:

  • 啊,有趣的做法,+1,虽然我不知道你和我之间哪个更有效(或者它对小字符串或“冷”代码区域很重要)
  • 我认为,在 else-block 中 text.append(" " + s); 会快一点。
  • 那不会做同样的事情吧? (现在它用operator= 覆盖了之前的内容,但append 就像将其更改为+=;我认为这可能是原始代码中的错字)
  • @SethCarnegie:但这就是我们想要的。抱歉,它应该是+=,而不是+。我不知道为什么人们投票它并不完全正确:P
  • 也是一个迂腐的注解,使用if (!text.empty()) 可能比if (text != "") 更好
【解决方案3】:

我所做的大部分工作都类似于@Nawaz 已经发布的内容——从istringstream 读取字符串以获取不带空格的数据,然后在每个字符串之间插入一个空格。但是,我会使用 previous answer 中的 infix_ostream_iterator 来获得(IMO)稍微更清晰/更清晰的代码。

std::istringstream buffer(input);

std::copy(std::istream_iterator<std::string>(buffer),
          std::istream_iterator<std::string>(),
          infix_ostream_iterator<std::string>(result, " "));

【讨论】:

    【解决方案4】:
    #include <boost/algorithm/string/trim_all.hpp>
    string s;
    boost::algorithm::trim_all(s);
    

    【讨论】:

      【解决方案5】:

      如果您查看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(" "));
      }
      

      【讨论】:

      • 尝试添加代码块但没有运气..添加答案,但我认为这是正确的轨道。
      【解决方案6】:

      这是一个使用正则表达式的可能版本。我的 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;
      }
      

      【讨论】:

        猜你喜欢
        • 2010-09-18
        • 1970-01-01
        • 2010-12-05
        • 2013-02-28
        • 1970-01-01
        • 2020-09-09
        • 2011-03-23
        相关资源
        最近更新 更多