我如何在c++
中执行与以下代码类似的操作:
//Lang: Java
string.replaceAll(" ", " ");
此代码段将使用单个空格替换字符串中的所有多个空格。
答案 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::remove
和remove_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)
如何处理所有类型的空白