c ++矢量擦除功能不适用于特定的单词?

时间:2015-06-05 00:10:12

标签: c++ vector

我在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>

3 个答案:

答案 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());