2

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
Tim
  • 2,051
  • 17
  • 36
user1231229
  • 61
  • 1
  • 8

3 Answers3

2

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.

Peter
  • 7,216
  • 2
  • 34
  • 46
1

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...

Tim
  • 2,051
  • 17
  • 36
  • I tried your segment now it gives me : WuManber.cpp: In member function ‘void WuManber::Initialize(const std::vector&, bool, bool, bool)’: WuManber.cpp:63:42: error: no matching function for call to ‘std::vector::erase(__gnu_cxx::__normal_iterator >) const’ error – user1231229 Feb 26 '12 at 10:29
  • 1
    You try to modify a const vector reference. This is why the compiler is complaining. – Tim Feb 26 '12 at 10:40
0

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.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760