стирание вектора ожидает 2 аргумента ошибки

0

Я использую Code :: Blocks, и вот мой код ниже в c++.

void removeEvenLength(vector<string> &vec)
{
    for (vector<string>::reverse_iterator i = vec.rbegin(); i != vec.rend(); ++i)
    {
        string word = *i;
        if (word.length() % 2 == 0)
            vec.erase(i);
    }
}

Эта функция принимает вектор строк и удаляет слово, которое равно длине букв. Я получаю сообщение об ошибке, в котором говорится, что для удаления требуется 2 аргумента, но согласно документации c++, все должно быть в порядке. Вы знаете, что не так?

  • 2
    Вы знаете, что если вы модифицируете вектор, итераторы (и указатели) в нем становятся недействительными? Вы можете использовать возвращаемое значение erase (см., Например, эту ссылку ).
  • 2
    Используйте std::remove_if .
Показать ещё 4 комментария
Теги:

2 ответа

1
Лучший ответ

Если вы абсолютно должны использовать erase() с обратным итератором, вот как это сделать:

void removeEvenLength(vector<string> &vec)
{
    for (vector<string>::reverse_iterator i = vec.rbegin(); i != vec.rend();)
    {
        string word = *i;
        if (word.length() % 2 == 0) {
            vector<string>::iterator newi = vec.erase(i.base() - 1);
            i = vector<string>::reverse_iterator(newi);
        } else {
            ++i;
        }
    }
}

Но это не лучший способ удалить все строки четной длины в векторе по ряду причин. Способ сделать это следующим образом (он называется "стирать-удалить" идиому):

struct IsEven {
    bool operator()(const string &s) const {
        return (s.size() % 2) == 0;
    }
};

vec.erase(
    std::remove_if(vec.begin(), vec.end(), IsEven()),
    vec.end()
);

Или в С++ 11 вы можете использовать лямбда вместо отдельного функтора:

vec.erase(
    std::remove_if(
        vec.begin(), vec.end(), 
        [](const string &s) { return (s.size() % 2) == 0; }
    ),
    vec.end()
);
  • 0
    У меня есть несколько вопросов. Во-первых, почему вы сначала создали объект struct? Во-вторых, я прочитал документацию по remove_if, где говорилось, что третий аргумент является функцией предиката, так как возможно, что вы использовали IsEven (), когда он был определен только как объект структуры. В-третьих, я хочу уточнить идею vec.erase (). Таким образом, функция remove_if возвращает диапазон элементов, которые делают предикат истинным (значения указателя), и все эти элементы удаляются методом erase ()?
  • 0
    (1) Вы можете сделать это с помощью функции, но структура или лямбда более удобны для встраивания. (2) Если в прочитанной вами документации написано, что remove_if должна принимать функцию, то это неверно. Это займет все, что можно назвать. В этом случае экземпляр IsEven может быть вызван, потому что он перегружен operator() . В C ++ это называется функтором. (3). Да, remove_if возвращает конец диапазона, которые являются ложными, что, следовательно, также является началом диапазона, которые являются истинными. Призыв стереть удаляет истинные.
0

Если вы видите, например, эту ссылку, вы увидите, что erase принимает iterator или const_iterator, а не reverse_iterator. Поэтому вы не можете использовать его при повторном обратном направлении.

Кроме того, как было предложено Chris в комментарии, вы можете использовать std::remove_if. Связанная ссылка содержит пример того, как ее использовать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню