我无法理解这一点。我试图删除字符串中所有出现的某个字符,直到字符串变空。我知道我们可以通过使用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'。 为什么会这样?这是擦除/删除内部如何工作的原因吗?
答案 0 :(得分:6)
您获得的结果是因为 简单的解决方案是创建一个临时变量,例如, 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
的引用