2012-01-29 12 views
12

He creado una función para ejecutar un vector de cadenas y eliminar cualquier cadena de longitud 3 o menos. Esta es una lección sobre el uso de la biblioteca de Algoritmos STL.erase() después de realizar remove_if()

Tengo problemas porque las funciones funcionan pero no solo elimina las cadenas de longitud 3 o menos, sino que también agrega la cadena "vector" al final.

La salida debe ser

This test vector 

y en su lugar es

This test vector vector" 

¿Cómo puedo solucionarlo?

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

Respuesta

23

Es más fácil de entender esto si separada de los estados:

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

Estas 2 líneas hacen lo mismo como tu única línea. Y debería quedar claro ahora qué es el "error". remove_if, funciona primero. Se repite en todo el vector y mueve todas las entradas "seleccionadas" "hasta el final" (mejor dicho: mueve las entradas no seleccionadas al frente). Después de que se ha ejecutado devuelve un iterador a la posición "último" de la izquierda sobre las entradas, algo así como:

esta
prueba
vector
prueba < - puntos de iterador aquí
vector

Luego ejecuta borrar con un solo iterador. Eso significa que borra un único elemento apuntado, por lo que borra el elemento "prueba". - Lo que sobra es lo que estás viendo.

solucionarlo simplemente borrar a partir del vector devuelto por remove_if hasta el final() .:

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

Grandes detalles. ¡Muchas gracias por aclarar lo que está pasando! – MCP

+2

Esto podría morder aún más si 'myVector' estuviera vacío. Entonces 'iter' sería igual a' myVector.end() ', y borrar usando' erase (iter) 'llevaría a UB. – Ruslan

10

usted debe utilizar la forma de dos parámetros de borrado:

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

Gran respuesta. ¡Gracias! – MCP

Cuestiones relacionadas