2012-01-29 1 views
12

Ho creato una funzione per scorrere un vettore di stringhe e rimuovere qualsiasi stringa di lunghezza 3 o inferiore. Questa è una lezione sull'utilizzo della libreria Algoritmo STL.cancella() dopo aver eseguito remove_if()

Ho problemi nel fatto che le funzioni funzionano ma non solo elimina stringhe di lunghezza 3 o meno ma aggiunge anche la stringa "vettore" alla fine.

l'uscita dovrebbe essere

This test vector 

e invece è

This test vector vector" 

Come posso risolvere il problema?

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

risposta

23

È più facile capire questo se separare le normative:

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

Queste 2 linee fanno lo stesso come la tua singola linea. E dovrebbe essere chiaro ora qual è il "bug". remove_if, funziona prima. Itera su tutto il vettore e sposta tutte le voci "selezionate" fino alla fine "(meglio dire: sposta le voci non selezionate in primo piano). Dopo che ha eseguito restituisce un iteratore alla posizione di "ultimo" della sinistra su voci, qualcosa di simile:

questo
prova
vettore
prova < - punti iteratore qui
vettore

Quindi si esegue la cancellazione con un singolo iteratore. Ciò significa che cancelli un singolo elemento puntato su - così cancelli l'elemento "test". - Ciò che rimane è ciò che stai vedendo.

per risolvere il problema è sufficiente cancellare dal vettore restituito da remove_if fino alla fine() .:

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

Grandi dettagli. Grazie mille per chiarire cosa sta succedendo! – MCP

+2

Questo avrebbe morso ancora di più se 'myVector' fosse vuoto. Quindi 'iter' sarebbe uguale a' myVector.end() ', e cancellare usando' erase (iter) 'porterebbe a UB. – Ruslan

10

si dovrebbe utilizzare la forma a due parametri di cancellazione:

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

Grande risposta. Grazie! – MCP