Why do I get a segmentation fault while iterating through this vector?
I need to go through this vector and delete the duplicates. A segmentation fault is occurring somewhere within this code. My guess is that it has something to do with deleting elements while the iterator is going through, but I don't really have a concrete understanding of how these iterators are actually working yet, so I can't figure it out.
vector<char *>::iterator iter;
for (iter = v->begin(); iter != v->end()-1; iter++ )开发者_如何转开发{
char *aString = *iter;
int n = 1;
while(iter+n != v->end()){
int comparison = strcmp(aString, *(iter+n));
if(comparison == 0){
v->erase(iter + n);
}
n++;
}
}
Really, you just have a couple off-by-one problems here. You were comparing incorrectly against end()
and incrementing n
when you erased an element:
for (iter = v->begin(); iter != v->end()-1; iter++ ){
^^^^^^^^
And
while(iter+n != v->end())
^^
The following will do what you want (and demonstrate that it works):
int main()
{
std::vector<const char*> v (4, "this");
std::vector<const char *>::iterator iter;
for (iter = v.begin(); iter < v.end(); iter++ ) {
std::cout << *iter << " ";
}
std::cout << std::endl;
for (iter = v.begin(); iter < v.end(); iter++ ){
const char *aString = *iter;
int n = 1;
while(iter+n < v.end()){
int comparison = strcmp(aString, *(iter+n));
if(comparison == 0){
v.erase(iter + n);
}
else
n++;
}
}
for (iter = v.begin(); iter < v.end(); iter++ ) {
std::cout << *iter << std::endl;
}
}
Output is:
this this this this
this
You are not properly iterating through the remainder of the vector. An alternative to what Beta suggested is to use erase-remove with remove_if. Like this:
bool compare_strings(char * aString,char * bString)
{
return 0==strcmp(aString,bString);
}
void remove_duplicates(vector<char *> * v)
{
vector<char *>::iterator iter;
for (iter = v->begin(); iter != v->end(); iter++ ) {
v->erase(std::remove_if(iter+1,v->end(),compare_strings),v->end());
}
}
When you erase an element from the vector, the vector gets one element shorter. Try this:
if(comparison == 0){
v->erase(iter + n);
}
else{
n++;
}
Erasing from a vector invalidates all iterators from the erasee onwards, so you should probably not construct your loop the way you do, and rather use a standard idiom like this:
for (auto it = v.begin(); it != v.end(); ++it) // no end() - 1 -- may not be legal!
{
for (auto jt = it; jt != v.end(); )
{
if (jt == it) continue;
if (strcmp(*it, *jt) == 0)
{
jt = v.erase(jt);
}
else
{
++jt;
}
}
}
This code avoids the check for an empty vector, which your code fails to account for.
精彩评论