【问题标题】:Replace multiple spaces with one space in a string用一个空格替换字符串中的多个空格
【发布时间】:2012-01-11 19:44:47
【问题描述】:

我将如何在c++ 中执行类似于以下代码的操作:

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

此代码-sn-p 会将字符串中的所有多个空格替换为单个空格。

【问题讨论】:

标签: c++ string replace


【解决方案1】:
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::removeremove_if 一样,std::unique 实际上并没有使容器变小,它只是将末尾的元素移动到更靠近开头的位置。它返回一个指向新范围末尾的迭代器,因此您可以使用它来调用erase 函数,该函数是字符串类的成员函数。

分解它,擦除函数有两个参数,一个开始迭代器和一个结束迭代器,用于擦除一个范围。对于它的第一个参数,我传递了std::unique 的返回值,因为这是我要开始擦除的地方。对于它的第二个参数,我传递了字符串的结束迭代器。

【讨论】:

  • 酷,以前从未见过。 +1
  • @Seth:我也没有,我突然想到了。
  • 你甚至可以先template<char Remove> bool BothAre(char lhs, char rhs) { return lhs == rhs && lhs == Remove; } 然后str.erase(std::unique(str.begin(), str.end(), BothAre<' '>), str.end()); 让它有点通用,也可以用于其他角色
  • @user386911 std::unique 将接收到的两个迭代器之间的所有连续重复字符移动到 end 迭代器,以便所有字符都位于字符串的末尾。然后它将迭代器返回到它移动到字符串末尾的所有字符的开头,并将该迭代器传递给str.erase,它需要两个迭代器并删除它们之间的所有字符。 tl;dr:所有重复的空格都通过unique 出现在字符串的末尾,然后erase 将它们删除。
  • @Seth: "所有字符都以字符串结尾" std::unique 和 std::remove 都不需要这样做,而且我不知道他们有任何实现。他们只是将非重复元素从末端复制或移动到前面。
【解决方案2】:

所以,我尝试了一种使用 std::remove_if 和 lambda 表达式的方法——尽管在我看来它似乎仍然比上面的代码更容易理解,但它没有那种“哇,真棒,没想到你能做到这一点” 事情到它..无论如何我仍然发布它,如果只是为了学习目的:

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

EDIT 意识到 std::remove_if 返回一个可以使用的迭代器.. 删除了不必要的代码。

【讨论】:

  • str.erase(iter, str.end());而不是 in.erase(iter, in.end());
【解决方案3】:

Benjamin Lindley 答案的变体,它使用 lambda 表达式使事情变得更简洁:

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

【讨论】:

  • 得到[=]没用,用[]就行了
【解决方案4】:

为什么不使用正则表达式:

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

【讨论】:

  • C++11 还包括 regex 库,如果使用 boost 有问题,可以使用它。
  • 没有什么好理由,只是算法柔术更有趣。
  • boost 不是标准库的一部分吗?
  • @OwolabiEzekielTobiloba 不,不是。
【解决方案5】:

isspace(lhs) && isspace(rhs) 处理所有类型的空格怎么样

【讨论】:

  • 请在您自己尝试并提供示例工作代码后回答
猜你喜欢
  • 2011-09-04
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 2021-08-24
  • 2021-10-29
相关资源
最近更新 更多