【问题标题】:erase() after performing remove_if()执行 remove_if() 后擦除()
【发布时间】:2012-02-21 15:46:51
【问题描述】:

我创建了一个函数来遍历字符串向量并删除长度为 3 或更短的任何字符串。这是使用 STL 算法库的一课。

我在函数工作时遇到了麻烦,但它不仅会删除长度为 3 或更短的字符串,而且还会将字符串“vector”附加到末尾。

输出应该是

This test vector

其实是

This test vector vector"

我该如何解决?

/*
* using remove_if and custom call back function, write RemoveShortWords 
* that accepts a vector<string> and removes all strings of length 3 or
* less from it. *shoot for 2 lines of code in functions.
*/

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <iterator>
using namespace std;

bool StringLengthTest(string test) //test condition for remove_if algo.  
{
    return test.length() <= 3;
}

void RemoveShortWords(vector<string> &myVector)
{
    //erase anything in vector with length <= 3
    myVector.erase(remove_if(myVector.begin(),
                             myVector.end(),
                             StringLengthTest));
}

int main ()
{
    //add some strings to vector
    vector<string> myVector;
    myVector.push_back("This");
    myVector.push_back("is");
    myVector.push_back("a");
    myVector.push_back("test");
    myVector.push_back("vector");

    //print out contents of myVector (debugging)
    copy(myVector.begin(), myVector.end(), ostream_iterator<string>(cout," "));
    cout << endl; //flush the stream

    RemoveShortWords(myVector); //remove words with length <= 3

    //print out myVector (debugging)
    copy(myVector.begin(), myVector.end(), ostream_iterator<string>(cout," "));
    cout << endl;

    system("pause");
    return 0;
}

【问题讨论】:

    标签: c++ erase-remove-idiom


    【解决方案1】:

    如果将语句分开,最容易理解这一点:

    auto iter(remove_if(myVector.begin(), myVector.end(), StringLengthTest));
    myVector.erase(iter);
    

    这两行与您的单行相同。现在应该清楚“错误”是什么。 remove_if,首先工作。它遍历整个向量并将所有“选定的”条目“移动到末尾”(更好地说:它将未选定的条目移动到前面)。运行后,它会将迭代器返回到剩余条目的“最后”位置,例如:

    这个
    测试
    矢量
    测试 向量

    然后您使用单个迭代器运行擦除。这意味着您擦除了指向的单个元素 - 因此您擦除了“测试”元素。 - 剩下的就是你所看到的。

    要修复它,只需从 remove_if 返回的向量中擦除到 end()。:

    myVector.erase(remove_if(myVector.begin(), myVector.end(), StringLengthTest), myVector.end()); //erase anything in vector with length <= 3
    

    【讨论】:

    • 很棒的细节。非常感谢您澄清发生了什么!
    • 如果myVector 是空的,这会更严重。那么iter 将等于myVector.end(),使用erase(iter) 擦除将导致UB。
    【解决方案2】:

    你应该使用erase的两个参数形式:

    myVector.erase(remove_if(myVector.begin(), myVector.end(), StringLengthTest),
                   myVector.end());
    

    【讨论】:

      猜你喜欢
      • 2017-06-26
      • 2021-07-03
      • 2019-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-16
      相关资源
      最近更新 更多