vector< std::string > iterator

I'm only now just teaching myself about vectors.

I've played around with std::vector< int > and noticed that the std::vector< int >::iterator I created was incrementable.

When I try to do this with a std::vector< std::string >::iterator in the following code, I get the following error:
vector iterator not incrementable



1
2
3
4
5
6
7
while( sIter != sVec.end() )
{
	if( sIter == find( sVec.begin(), sVec.end(), input ) )
		sVec.erase( sIter );

	++sIter;
}


Can anyone tell me why this is happening? As this is an iterator, shouldn't this be incrementable?

Thanks for any help.


EDIT:

I fixed this with the following code:

1
2
3
4
5
6
7
8
9
10
while( sIter != sVec.end() )
{
	if( sIter == find( sVec.begin(), sVec.end(), input ) )
	{
		sVec.erase( sIter );
		break;
	}

	++sIter;
}


How come I can't iterate after erasing something? I made sure that the entry I delete wasn't at the end of the vector, as not to pass the end of the vector. Also, each input was different, so I was only erasing one entry.
Last edited on
What does your find() method do and did you set:
 
sIter = sVec.begin();

before you started the while loop?
Last edited on
Yeah, I set sIter, and 'find' is searching for user input. Here is the full function:

stdafx.h:
1
2
typedef std::vector< std::string > strVector;
typedef std::vector< std::string >::iterator strVecIter;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "stdafx.h"

void stringVec()
{
	std::string input;
	strVector sVec;

	do
	{
		std::cout << "Enter strings for vector input. \"exit\" to quit entry.\n";

		do
		{
			std::cout << "String: ";

			std::getline( std::cin, input, '\n' );

			sVec.push_back( input );

		}while( input != "exit" );

		if( input == "exit" )
			sVec.erase( sVec.end() - 1 );

		std::cout << "\nEntered strings: \n";
		outputVecStr( sVec );

		sort( sVec.begin(), sVec.end() );

		std::cout << "\nSorted strings: \n";
		outputVecStr( sVec );

		std::cout << "\nType a name to erase: ";

		std::getline( std::cin, input, '\n' );

		strVecIter sIter = sVec.begin();

		while( sIter != sVec.end() )
		{
			if( sIter == find( sVec.begin(), sVec.end(), input ) )
			{
				sVec.erase( sIter );
				break;
			}

			++sIter;
		}

		std::cout << "\nVector with string removed:\n";
		outputVecStr( sVec );


		std::cout << "\n\nPress ENTER to retry, or any other key to exit.\n\n";
	}while( _getch() == 13 );
}
Last edited on
I don't see why you need a loop in the deletion part. The find() algorithm will return an iterator pointing to the found element, or to sVec.end() if the data was not found. So to delete the requested string you should do:

1
2
3
4
5
if (sIter = find(sVec.begin(), sVec.end(), input) != sVec.end())
{
    sVec.erase(sIter);
    break;
}


As you have it right now it will only erase successfully the requested string if the string is the first string in the array.

And to answer your question: Iterators usually become invalid when the underlying collection is changed. You change the collection by removing a string from it and this means that if you want to iterate, you have to start over.
Thanks. I thought I had to itterate through the vector.

And come to think of it, I'm sure I read something yesterday, about iterators becoming invalid. Thanks for the help!

EDIT:
Actually, I've just tried this without the 'while' loop. I do need to iterate through, or I never actually erase anything.
Last edited on
I'm sure I read something yesterday, about iterators becoming invalid
Yes, after erase() the iterator is invalid.

You can do it like so:
1
2
3
4
5
6
7
while( sIter != sVec.end() )
{
	if( sIter == find( sVec.begin(), sVec.end(), input ) )
		sIter = sVec.erase( sIter );
	else
		++sIter;
}


EDIT: Ok, that abouve does not make too much sense, so:
1
2
3
4
5
6
while( sIter != sVec.end() )
{
	sIter = find(sIter, sVec.end(), input );
	if(sIter != sVec.end())
		sIter = sVec.erase(sIter);
}

Last edited on
Ok, I fixed it.
I never tried your code, coder777, but you're not iterating through the vector.

Here's what I did:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void eraseVecStr( strVector &v, const std::string i )
{
	strVecIter sIter = v.begin();//set iter to the start of the vector

	while( sIter != v.end() )
	{
		if( sIter == find( v.begin(), v.end(), i ) )//if there's a match of element and input
		{
			v.erase( sIter );//erase element
			break;//break ( exit function )
		}

		++sIter;//iterare if there's no match, to check next element
	}
}
Last edited on
find already gives you an iterator that you can pass to erase, so there's no need to perform a find on the entire vector once for each of its elements. If anything, the comparison should be if (*sIter==i)
And that's exactly what find does, so...:

1
2
3
4
5
void eraseVecStr(strVector& v,const std::string& i)
{
  strVecIter it=find(v.begin(),v.end(),i);
  if (it!=v.end())v.erase(it);
}
Last edited on
Thanks a lot, Athar. And coder777! I just realised your code was right too! I just tried it.

The help is much appreciated, thanks!
My approach erases all appearance of 'input' while Athars just the first.
There's no need to iterate because find() erase() do.
Oh right, thanks!

I did do that, but by making the function a bool and returning true if deleted. And then from that, going back into the function, until a false was returned.
If you actually want to remove all matches, you should use remove_if, which does this in linear time (instead of quadratic time, like you have it now).
so, remove_if will iterate through the vector once and remove all that are the same, rather than the way I did it, to call a function until a delete was not made?
Basically, although you have to use the erase-remove idiom:

vec.erase( remove_if(vec.begin(), vec.end(), input), vec.end() );
Ok, I get it.

erase > if, while iterating through, you return true on a comparison, until the end of the vector is met.

What's idiom?

EDIT:
I just googled it, I'm guessing it's this?
Iterative Development and Implementation of an Object-Oriented Methodology

NOT part of the EDIT:
Thanks a lot, all of you. Been a great help! Don't hesitate to help more if you have some good techniques with vectors! lol
Last edited on
What's idiom?

idiom=terminology or wording;)
Topic archived. No new replies allowed.