user1231229
user1231229

Reputation: 61

erase element from vector

I have the following vector passed to a function

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

I want to erase any element that is less in length than 2 I tried the following but it didn't compile even can you tell me what I am missing here.

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

Upvotes: 2

Views: 2044

Answers (3)

Peter
Peter

Reputation: 7324

On top of the problems others have pointed out, it's a bad idea to erase items from the vector as you iterate over it. There are techniques to do it right, but it's generally slow and fragile. remove_if is almost always a better option for lots of random erasures from a vector:

#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());
}

In C++0x you can do that more concisely with a lambda function but the above is more likely to work on a slightly older compiler.

Upvotes: 2

Michael Burr
Michael Burr

Reputation: 340168

First, as Tim mentioned, the patterns parameter is a const reference, so the compiler won't let you modify it - change that if you want to be able to erase elements in it.

Keep in mind that iter 'points to' a pointer (a char const* to be specific). So you dereference the iterator to get to the string pointer:

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

Also, in the last line of the snippet, iter is assigned whatever erase() returns to keep it a valid iterator.

Note that erasing the element pointed to by iter will not free whatever string is pointed to by the pointer in the vector. It's not clear whether or not that might be necessary, since the vector might not 'own' the strings that are pointed to.

Upvotes: 0

Tia
Tia

Reputation: 2081

This cannot work, because if you erase something from your vector you invalidate your iterator.

It probably does not compile because you use your iterater in a wrong way. You might try iter->c_str or (*iter).c_str. On the other hand, give us the error message ;)

Next thing, you try to modify a const vector. This is why the compiler is complaining.

You could do this with an index, like this:

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

However, this is not very elegant, as I manipulate the counter...

Upvotes: 1

Related Questions