Почему я получаю ошибку сегментации при переборе этого вектора? - PullRequest
0 голосов
/ 02 октября 2011

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

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++;
    }
}

Ответы [ 4 ]

2 голосов
/ 02 октября 2011

На самом деле, у вас просто пара проблем одна за другой.Вы неправильно сравнивали с end() и увеличивали n при удалении элемента:

for (iter = v->begin(); iter != v->end()-1; iter++ ){
                                  ^^^^^^^^

И

while(iter+n != v->end())
             ^^

Следующее будет делать то, что вы хотите (и продемонстрировать, чтоработает):

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;
    }

}

Вывод:

это это это это
это

2 голосов
/ 02 октября 2011

Вы неправильно выполняете итерацию по оставшейся части вектора.Альтернативой тому, что предложила Бета, является использование erase-remove с remove_if.Как это:

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());
    }
}
1 голос
/ 02 октября 2011

Стирание из вектора делает недействительными все итераторы, начиная с стирания и далее, поэтому вам, вероятно, не следует создавать свой цикл так, как вы это делаете, а скорее использовать стандартную идиому, такую ​​как:проверьте наличие пустого вектора, который ваш код не может учесть.

1 голос
/ 02 октября 2011

Когда вы удаляете элемент из вектора, вектор становится на один элемент короче. Попробуйте это:

if(comparison == 0){
  v->erase(iter + n);
}
else{
  n++;
}
...