2012-01-29 14 views
12

Stworzyłem funkcję, aby uruchomić wektor ciągów i usunąć ciągi o długości 3 lub mniejszej. To jest lekcja korzystania z biblioteki algorytmów STL.erase() po wykonaniu remove_if()

Mam problem z tym, że funkcje działają, ale nie tylko usuwa ciągi o długości 3 lub mniejszej, ale także dodaje ciąg "wektor" do końca.

Wyjście powinno być

This test vector 

i zamiast to

This test vector vector" 

Jak mogę to naprawić?

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

Odpowiedz

23

Najłatwiej jest to zrozumieć, jeśli oddzielne sprawozdania:

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

te 2 linie zrobić to samo jako twoja pojedyncza linia. I teraz powinno być jasne, co to jest "błąd". remove_if, działa jako pierwszy. Powtarza on cały wektor i przenosi wszystkie "wybrane" wpisy "do końca" (lepiej powiedzieć: przesuwa niewybrane wpisy na początek). Po jego uruchomieniu zwraca iterator do pozycji „ostatniego” z lewej strony nad wpisami, coś jak:

to
testowe
wektorowe
testowe < - punkty iteracyjnej tutaj
wektorowe

Następnie uruchamia się kasowanie za pomocą pojedynczego iteratora. Oznacza to, że wymazujesz pojedynczy element wskazany na - tak, aby usunąć element "testowy". - To, co pozostaje, to to, co widzisz.

go naprawić po prostu wymazać z wektora zwróconej przez remove_if do końca() .:

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

Wspaniałe szczegóły. Dziękuję bardzo za wyjaśnienie, co się dzieje! – MCP

+2

To by było jeszcze bardziej bite, gdyby 'myVector' były puste. Wtedy 'iter' będzie równy' myVector.end() ', a kasowanie przy użyciu' erase (iter) 'doprowadzi do UB. – Ruslan

10

Powinieneś za pomocą formularza dwa parametru wymazane:

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

Wielkiej odpowiedź. Dzięki! – MCP

Powiązane problemy