我在c ++中使用了一个非常简单的函数,vector.erase(),这里有我所拥有的(我试图从.txt文件中删除这三个关键字的所有实例):< / p>
首先,我在两个单独的for循环中使用它来擦除<event>
和</event>
的所有实例,这非常有效,并输出编辑后的文本文件,不再包含这些单词的实例。
for (int j = 0; j< N-counter; j++) {
if(myvec[j] == "<event>") {
myvec.erase(myvec.begin()+j);
}
}
for (int j = 0; j< N-counter; j++) {
if(myvec[j] == "</event>") {
myvec.erase(myvec.begin()+j);
}
}
然而,当我添加第三个for循环来执行完全相同的操作时,实际上只需使用新关键字进行复制和粘贴,如下所示:
for (int j = 0; j< N-counter; j++) {
if(myvec[j] == "</LesHouchesEvents>") {
myvec.erase(myvec.begin()+j);
}
}
它编译并执行,但它完全破坏.txt文件,使其完全不可打开,当我捕捉它时,我只是得到一堆疯狂的符号。
我已经尝试切换这些for循环的顺序,甚至完全摆脱前两个for循环,我能想到的一切,唉它只是因为一些奇怪的原因不适用于关键字</LesHouchesEvents>
。
答案 0 :(得分:1)
我不知道这是否是您的具体问题,但这个循环几乎肯定不是您想要的。
请注意erase
的文档 - 它“移动”了剩下的元素。不幸的是,您的代码仍然会增加j
,这意味着您正在跳过下一个元素:
for (int j = 0; j< N-counter; j++) { // <- Don't increment j here
...
myvec.erase(myvec.begin()+j); // <- increment it only if this didn't happen.
}
您还需要调整循环的停止条件。
答案 1 :(得分:1)
你的循环没有考虑当erase()
来自vector
的元素时,其余元素的索引会相应减少。因此,一旦擦除了至少1个元素,你的循环最终将超过vector
的范围。你需要考虑到这一点:
std:string word = ...;
size_t count = N-counter;
for (int j = 0; j < count;) {
if(myvec[j] == word) {
myvec.erase(myvec.begin()+j);
--count;
}
else {
++j;
}
}
话虽如此,使用迭代器而不是索引会更安全。 erase()
返回一个迭代器,该迭代器紧跟在被删除元素后面的元素上。您可以使用std::find()
进行实际搜索:
#include <algorithm>
std::vector<std::string>::iterator iter = std::find(myvec.begin(), myvec.end(), word);
while (iter != myvec.end())
{
iter = myvec.erase(iter);
iter = std::find(iter, myvec.end(), word);
}
或者,您可以改为使用std::remove()
:
#include <algorithm>
myvec.erase(std::remove(myvec.begin(), myvec.end(), word), myvec.end());
答案 2 :(得分:0)
即使假设你正常工作,这几乎是从矢量中删除项目的最糟糕方式。
你几乎肯定想要删除/删除习惯用法,你可能想要在一次传递中进行所有比较,所以它是这样的:
std::vector<std::string> bad = {
"<event>",
"</event>",
"</LesHouchesEvents>"
};
myvec.erase(std::remove_if(my_vec.begin(), my_vec.end(),
[&](std::string const &s) {
return std::find(bad.begin(), bad.end(), s) != bad.end();
}),
my_vec.end());