Erase() после выполнения remove_if()
Я создал функцию для запуска вектора строк и удаления любых строк длиной 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;
}
Ответы
Ответ 1
Проще всего понять это, если вы разделите утверждения:
auto iter(remove_if(myVector.begin(), myVector.end(), StringLengthTest));
myVector.erase(iter);
Эти две строки делают то же, что и ваша одна строка. И теперь должно быть ясно, что такое "ошибка". remove_if, работает первым. Он выполняет итерацию по всему вектору и перемещает все "выбранные" записи "до конца" (лучше сказано: он перемещает не выбранные записи на передний план). После запуска он возвращает итератор в "последнюю" позицию левой записи, например:
это
тест
вектор
test < -тератор указывает здесь
вектор
Затем вы запускаете стирание с помощью одного итератора. Это означает, что вы удаляете один элемент, на который указывает, поэтому вы удаляете элемент "test". - То, что осталось, - это то, что вы видите.
Чтобы исправить это, просто удалите из вектора, возвращаемого remove_if, в конец().:
myVector.erase(remove_if(myVector.begin(), myVector.end(), StringLengthTest), myVector.end()); //erase anything in vector with length <= 3
Ответ 2
Вы должны использовать две формы формы стирания:
myVector.erase(remove_if(myVector.begin(), myVector.end(), StringLengthTest),
myVector.end());