#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— (который в случае вашего кода, который напрямую не использует итератор, будет работать таким же образом).Или вы можете использовать условие приращения, как в предыдущем ответе, но итератор должен быть правильно обновлен.