从String中删除字符直到它变空

时间:2015-01-13 15:36:24

标签: c++

我无法理解这一点。我试图删除字符串中所有出现的某个字符,直到字符串变空。我知道我们可以通过使用string :: erase和std :: remove的组合来删除std :: string中的所有字符出现,如下所示:

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

其中'。'是要删除的实际字符。如果我尝试删除某些字符,它甚至可以工作。现在让我们考虑以下字符串:' abababababababa'。我想要实现的目标是将这个字符串减少为灰烬,删除所有的开始,这将留给我几个b' s。然后删除所有那些会留下空字符串的b。当然这只是我的任务的一部分,但我可以缩小它的问题。这是我基于功能的上层组合的天真方法:

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

当然它不起作用,我似乎无法找出原因。通过调试应用程序,我可以看到" s"正在修改字符串。虽然如果我为删除第三个参数设置一个字符常量,但是s.erase ...工作正常,如果我尝试使用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'。 为什么会这样?这是擦除/删除内部如何工作的原因吗?

2 个答案:

答案 0 :(得分:6)

您有undefined behavior

您获得的结果是因为std::remove获取值按引用移除 ,一旦s[0]被移除,那么对它的引用会发生什么?< / p>

简单的解决方案是创建一个临时变量,例如, s[0],然后传递变量。

答案 1 :(得分: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(),那么原来的[0]是'a',但在remove()期间它将改为'b',剩下的代码会移除'b',所以结果不对。 就像Joachim所说的那样,将s [0]分配给一个临时变量。

代码是http://www.cplusplus.com/reference/algorithm/remove/?kw=remove

的引用