我在擦除一些向量元素时做错了什么?

时间:2015-07-26 15:40:46

标签: c++ string vector

这里我试图打印句子中每个单词的频率,该单词存储在vector string

void display_by_word (vector<string> vs) //pass by value is necessary because we need to delete the elements.
{
vector<string> :: size_type vec_size, i;
string to_cmp = vs[0];
int occ = 0;

for ( i = 0; i < vs.size(); ++i){

    vector <string> :: iterator it = vs.begin() + 1;
    occ = 1;

    for ( it ; it != vs.end(); ++it){

        if ( vs[i] == *it){

            vs.erase(it);
            occ++;
        }
    }

    cout << vs[i] << "     " << occ << endl;
}

}

有时它工作正常,但有时会崩溃。有什么不对?

3 个答案:

答案 0 :(得分:3)

请参阅http://en.cppreference.com/w/cpp/container/vector/erase

  

在擦除点[...]

之后或之后使迭代器和引用无效

erase发生后,您无法重复使用it,因为它已失效。它是未定义的行为,可能包括随机崩溃。

但是,erase返回删除后的元素的迭代器,如果它是最后一个元素则返回end(),这就是it = vs.erase(it);解决方案有效的原因。

或者,请考虑使用std::remove_if,然后使用双参数erase,即Erase-Remove Idiom。它可能比手写循环更优雅,更可读。或者只是重写整个函数以使用std::count_if

答案 1 :(得分:2)

你可能想要像这样重写循环

while(it != vs.end())
{
    if ( vs[i] == *it){

        it = vs.erase(it);
        occ++;
    }
    else
        it++;
}

答案 2 :(得分:1)

你可以这样做: ` for(it; it!= vs.end();){

    if ( vs[i] == *it){

        it = vs.erase(it);
        occ++;
    }
    else{
        ++it;
    }
}

`