从字符串中删除字符,直到它变为空

Removing Characters from String until it becomes empty

本文关键字:字符串 删除 字符      更新时间:2023-10-16

我无法解决这个问题。我正在尝试删除字符串中某个字符的所有出现,直到字符串变为空。我知道我们可以通过使用字符串::擦除和标准::删除的组合从 std::string 中删除所有出现的字符,如下所示:

s.erase(remove(s.begin(), s.end(), '.'), s.end());

其中"."是要删除的实际字符。如果我尝试删除某些字符,它甚至可以工作。现在让我们考虑以下字符串:"abababa"。我试图实现的是将这个字符串减少到灰烬,删除所有开始的"a",这将给我留下几个"b"。然后删除所有那些会给我留下空字符串的'b'。当然,这只是我任务的一部分,但我可以缩小范围解决这个问题。这是我基于上层函数组合的幼稚方法:

string s = "abababababababa";
while (!s.empty()) {
    ...
    s.erase(remove(s.begin(), s.end(), s[0]), s.end());
    ...
}

当然它不起作用,我似乎无法找出原因。通过调试应用程序,我可以看到"s"字符串是如何被修改的。虽然s.erase...如果我为 remove 的第三个参数设置一个字符常量,则工作正常,如果我尝试使用 char 变量,它会失败。以下是每次迭代后 s 字符串的外观:

Removing[a] from [abababababababa] Result: baaaaaaa
Removing[b] from [baaaaaaa] Result: a
Removing[a] from [a] Result: -

虽然我预计要执行 2 次操作,直到字符串变为空 - 如果我手动对字母进行硬编码并使用 s.erase 两次,这有效 - 实际上需要 3 次迭代。然而,最令人沮丧的部分是,当我在第一次迭代中删除"a"时,只删除了第一个"a"和所有其他"b"。为什么会这样?这是内部擦除/删除工作方式的原因吗?

你有未定义的行为

你得到

你得到的结果,因为你std::remove通过引用删除值,一旦删除了s[0],那么对它的引用会发生什么?

简单的解决方案是创建一个临时变量,例如赋值 s[0]它,并改为传递变量。

函数 remove() 模板的行为等效于:

template <class ForwardIterator, class T>
  ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val)
{
  ForwardIterator result = first;
  while (first!=last) {
    if (!(*first == val)) {
      *result = move(*first);
      ++result;
    }
    ++first;
  }
  return result;
}

如您所见,该函数会将与 val 不同的元素移动到范围的前面。所以在你的例子"ababababab",如果你像以前那样调用remove(),原来的s[0]是'a',但在remove()过程中会用'b'代替,剩下的代码会去掉'b',所以结果是不对的。就像 Joachim 说的,将 s[0] 赋值给一个临时变量。

该代码引用自 http://www.cplusplus.com/reference/algorithm/remove/?kw=remove