我试图从诸如"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/

10-11 23:12
查看更多