我试图从诸如"helloworld"
的字符串中删除连续重复的字符,并删除所有出现的重复字符。在这种情况下,它是'l'
,因此新字符串应为"heoword"
。我写了这样的代码:
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main() {
string s = "helloworld";
for (int i = 0; i < s.length() - 1; i++) {
if (s[i] == s[i+1]) {
s.erase(remove(s.begin(), s.end(), s[i]), s.end()); // PROBLEM
cout << s << endl; // printing `heowrld`, instead of `heoword`
}
}
return 0;
}
除非我像
s[i]
一样投射(char)s[i]
,否则上面的代码不起作用。我在运算符[]
中查找了字符串,它正在返回对该位置的字符的引用。 remove
方法还接受const T& val
作为要替换字符的参数。由于它们都是同一类型,为什么不能只将s[i]
用作remove
方法的参数?ps。这不是作业问题。通过将
s[i]
强制转换为remove
,我可以获得正确的输出,但是我想知道为什么需要强制转换s[i]
。 最佳答案
这里的问题是您移动了要从自己内心去除的价值。让我们来看看
#include <iostream>
int main()
{
int a = 5, b = 10;
int & ref = a;
std::cout << "a: " << a << " b: " << b << " ref: " << ref << "\n";
std::swap(a, b);
std::cout << "a: " << a << " b: " << b << " ref: " << ref << "\n";
}
如果您运行它,您将得到
a: 5 b: 10 ref: 5
a: 10 b: 5 ref: 10
如您所见,
ref
不会移动到现在跟随b
,而是停留在a
上(应该),并显示a
的新值。我们看到了同样的事情
s.erase(remove(s.begin(), s.end(), s[i]), s.end());
因为
s[i]
是对字符串中元素的引用,所以它的值随着remove交换元素而改变。因此,它删除了两个l
,然后又删除了最后一个o
,因为o
移到了l
以前占据的位置,但只有在它通过第一个o
后才这样做。字符串。之所以强制“修复”,是因为现在您不再引用字符串的元素。您创建一个临时变量,并使用该变量值删除
l
。关于c++ - 为什么需要转换算法remove()的参数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44574985/