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

时间:2011-12-02 20:16:55

标签: c++ string replace

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

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

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

5 个答案:

答案 0 :(得分: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());   

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

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

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

答案 1 :(得分:4)

所以,我尝试了一种方法,使用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());

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

答案 2 :(得分: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());

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

isspace(lhs) && isspace(rhs)如何处理所有类型的空白