удалить элемент из вектора

У меня есть следующий вектор, переданный функции

void WuManber::Initialize( const vector<const char *> &patterns, 
                      bool bCaseSensitive, bool bIncludeSpecialCharacters, bool bIncludeExtendedAscii )

Я хочу стереть любой элемент, длина которого меньше 2. Я пробовал следующее, но он не скомпилировался, даже вы можете сказать мне, что мне здесь не хватает.

for(vector<const char *>::iterator iter = patterns.begin();iter != patterns.end();iter++)
 {//my for start
 size_t lenPattern = strlen((iter).c_str);
 if ( 2 > lenPattern )
 patterns.erase(iter);
 }//my for end

person user1231229    schedule 26.02.2012    source источник


Ответы (3)


Это не может работать, потому что, если вы удалите что-то из своего вектора, вы аннулируете свой итератор.

Вероятно, он не компилируется, потому что вы неправильно используете свой итератор. Вы можете попробовать iter->c_str или (*iter).c_str. С другой стороны, дайте нам сообщение об ошибке;)

Далее вы пытаетесь изменить константный вектор. Вот почему компилятор жалуется.

Вы можете сделать это с помощью индекса, например:

for (int i = 0; i < patterns.size(); ++i) {
    size_t lenPattern = strlen(patterns[i]);
    if (2 > lenPattern) {
      patterns.erase(patterns.begin() + i);
      --i;
    }
}

Однако это не очень элегантно, так как я манипулирую счетчиком...

person Tim    schedule 26.02.2012
comment
Я попробовал ваш сегмент, теперь он дает мне: WuManber.cpp: В функции-члене 'void WuManber::Initialize(const std::vector‹const char*›&, bool, bool, bool)': WuManber.cpp:63:42 : ошибка: нет соответствующей функции для вызова 'std::vector‹const char*›::erase(__gnu_cxx::__normal_iterator‹const char* const*, std::vector‹const char*› ›) const' ошибка - person user1231229; 26.02.2012
comment
Вы пытаетесь изменить ссылку на константный вектор. Вот почему компилятор жалуется. - person Tim; 26.02.2012

Помимо проблем, на которые указывали другие, плохой идеей является стирание элементов из вектора по мере его повторения. Есть методы, чтобы сделать это правильно, но, как правило, это медленно и хрупко. remove_if почти всегда лучший вариант для множества случайных стираний из вектора:

#include <algorithm>
bool less_than_two_characters(const char* str) { return strlen(str) < 2; }

void Initialize(vector<const char*>& v) {
    v.erase(std::remove_if(v.begin(), v.end(), less_than_two_characters), v.end());
}

В C++0x вы можете сделать это более лаконично с помощью лямбда-функции, но приведенное выше, скорее всего, будет работать на более старом компиляторе.

person Peter    schedule 26.02.2012

Во-первых, как упомянул Тим, параметр patterns является постоянной ссылкой, поэтому компилятор не позволит вам изменить его - измените его, если хотите стереть элементы в нем.

Имейте в виду, что iter "указывает" на указатель (точнее, на char const*). Таким образом, вы разыменовываете итератор, чтобы добраться до указателя строки:

size_t lenPattern = strlen(*iter);
if ( 2 > lenPattern )
iter = patterns.erase(iter);

Кроме того, в последней строке фрагмента iter назначается все, что возвращает erase(), чтобы он оставался допустимым итератором.

Обратите внимание, что стирание элемента, на который указывает iter, не освобождает любую строку, на которую указывает указатель в векторе. Неясно, может ли это быть необходимо, поскольку вектор может не «владеть» строками, на которые указывают.

person Michael Burr    schedule 26.02.2012