C Vector.erase(), вызывающий ошибку сегментации

#c #vector #segmentation-fault

#c #вектор #ошибка сегментации

Вопрос:

У меня есть вектор C , и в нем есть несколько пустых элементов. Я хотел удалить все пустые строковые элементы из вектора. Я попробовал этот код:

 for (i = 0; i < myvector.size();i  ) {
  if (myvector[i] == "") {
    myvector.erase(myvector.begin() i);
  }
}
  

Когда я запускаю этот код, я получаю ошибку сегментации. С этим что-то не так? Или этот код работает у кого-нибудь из вас?

Комментарии:

1. Ваша реальная проблема с логикой, конечно, заключается в том, что вы увеличиваете значение i , когда не должны.

2. В этом коде нет ничего, что могло бы вызвать сбой сегментации из ниоткуда. (Конечно, фактически не удается стереть все пустые элементы). У вас, должно быть, какая-то другая проблема в вашей программе (например, более раннее повреждение кучи или объекты в вашем векторе не имеют правильной семиантики значений).

3. Как только единообразное стирание контейнера в STL станет стандартом, мы сможем сказать std::erase_each_if(myvector, std::mem_fn(amp;std::string::empty));

4. @KerrekSB, Круто, не знал, что такое бывает. У меня уже есть функция для этого, но все же.

5. @chris: Конечно, у каждого уже есть функция для этого — вот почему это рассматривается для стандартизации 😉

Ответ №1:

Похоже, вам нужна обычная идиома удаления-erase:

 #include <algorithm>
#include <functional>

myvector.erase(std::remove_if(myvector.begin(), myvector.end(),
                              std::mem_fn(amp;std::string::empty)),
               myvector.end());
  

Ответ №2:

Если у вас есть, например, vec=[«A»,»»», «B»,»C»] и вы удаляете элемент a[1], теперь ‘vec’ имеет длину 3, а не 4, поэтому vec[3] вызывает ошибку сегментации.

Попробуйте это:

 for (vector<...>::iterator i=myvector.begin(); 
              i != myvector.end(); /* do nothing here */) {
   if (i->empty()) {
      i=myvector.erase(i);
   } else {
       i;
   }
}
  

Однако решение Керрека более элегантное.

Комментарии:

1. Ваш итератор становится недействительным. И myvector[i] недопустимо. (И interator смеется)

2. @FedericoReghenzani спасибо и за ваш ответ. Сначала я не мог заставить это работать, но теперь это работает.

3. 1) достаточно постоянных итераторов; 2) *i == "" выглядит неуклюже, почему бы и нет i->empty() ?

4. Если вам интересно узнать о segfault, сравните его с этим .

5. @chris Я только что отредактировал с тем же исправлением 🙂 Благодарим вас за все комментарии и приносим извинения за ошибки

Ответ №3:

Прежде всего, прошу прощения за мой английский (я бразилец и пользуюсь переводчиком Google). Но ваша проблема заключается не только в удалении элемента за пределами вектора, но и в доступе к его элементу. Подумайте о следующей ситуации: у меня есть вектор v = {1, 4, 2}, и я хочу исключить все четные числа, используя for и итератор. Когда итератор достигает второго элемента (v [2]), он исключает 4, создавая вектор {1,2}. Но перед выходом из цикла for итератор все еще указывает на второй элемент (v [2]), который является последним элементом. При завершении итератор будет увеличен (i ) и будет равен v.end (). Следовательно, даже если это не приведет к ошибке сегментации, алгоритм не удалит все четные числа и, если бы v было равно {1,3,4}, это привело бы к ошибке сегментации. Чтобы исправить это, прямо при использовании v.erase () используйте i— (который в случае вашего кода, который напрямую не использует итератор, будет работать таким же образом).Или вы можете использовать условие приращения, как в предыдущем ответе, но итератор должен быть правильно обновлен.