MCP MCP - 1 year ago 118
C++ Question

erase() after performing remove_if()

I've created a function to run through a vector of strings and remove any strings of length 3 or less. This is a lesson in using the STL Algorithm library.

I'm having trouble in that the functions work but not only does it delete strings of length 3 or less but it also appends the string "vector" to the end.

The output should be

This test vector

and instead it is

This test vector vector"

How can I fix it?

* 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

int main ()
//add some strings to vector
vector<string> myVector;

//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;

return 0;

Answer Source

It is easiest to understand this if you seperate the statements:

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

These 2 lines do the same as your single line. And it should be clear now what the "bug" is. remove_if, works first. It iterates over the whole vector and moves all "selected" entries "to the end" (better said: it moves the non selected entries to the front). After it has run it returns an iterator to the "last" position of the left over entries, something like:

test <- iterator points here

Then you run erase with a single iterator. That means you erase a single element pointed at - so you erase the "test" element. - What is left over is what you are seeing.

To fix it simply erase from the vector returned by remove_if to the end().:

myVector.erase(remove_if(myVector.begin(), myVector.end(), StringLengthTest), myVector.end()); //erase anything in vector with length <= 3
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download