用字符串中的一个空格替换多个空格

eve*_*odd 21 c++ string replace

我将如何做c++类似于以下代码的事情:

//Lang: Java
string.replaceAll("  ", " ");
Run Code Online (Sandbox Code Playgroud)

此代码段将使用单个空格替换字符串中的所有多个空格.

Ben*_*ley 63

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());   
Run Code Online (Sandbox Code Playgroud)

这是如何工作的.将std::unique有两种形式.第一种形式通过一个范围并删除相邻的重复.所以字符串"abbaaabbbb"变成"abab".我使用的第二种形式采用一个谓词,该谓词应该采用两个元素,如果它们应该被视为重复,则返回true.我写的功能就是BothAreSpaces为了这个目的.它确切地确定了它的名字含义,它的两个参数都是空格.因此,当与之结合使用时std::unique,删除重复的相邻空格.

就像std::remove并且remove_if,std::unique实际上并没有使容器变小,它只是将元素移动到接近开头的末端.它将迭代器返回到范围的新结尾,因此您可以使用它来调用erase函数,该函数是字符串类的成员函数.

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

  • @Seth:我也没有,它突然来到我身边. (3认同)
  • @Seth:*"所有的角色最终都在字符串的末尾"*< - 常见的神话.这样做不需要`std :: unique`或`std :: remove`,我也不知道它们的任何实现.他们只是将非重复元素从末端复制或移动到前端. (3认同)
  • @ user386911`std :: unique`将它接收的两个迭代器之间的所有连续重复字符移动到结束迭代器,以便所有字符最终都在字符串的末尾.然后它将迭代器返回到它移动到字符串末尾的所有字符的开头,然后将该迭代器传递给`str.erase`,它接受两个迭代器并删除它们之间的所有字符.tl; dr:所有重复的空格都通过`unique`结束在字符串的末尾,然后`erase`删除它们. (2认同)

pau*_*l23 5

因此,我尝试了使用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());
Run Code Online (Sandbox Code Playgroud)

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