我正在尝试从"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
方法的参数?
P.S。这不是作业问题。通过在s[i]
中投射remove
,我可以获得正确的输出,但我想知道为什么我需要投射s[i]
。
答案 0 :(得分:2)
这里的问题是你移动值从你自己身下移除。让我们看看
#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]
是对字符串中元素的引用,因此当删除交换元素时,其值会发生变化。因此它删除了l
两个,然后删除了最后o
,因为o
被移动到l
曾经占据的相同位置,但它只会在它传递了字符串中的第一个o
。
施放“修复”这个的原因是因为现在你不再引用字符串的元素了。您创建一个临时变量,并使用该变量值来删除l
。