Вы просматриваете список с указателем на указатель узла, что является хорошей идеей. (Однако указывать тип указателя LIST
не очень хорошая идея.) В коде yur есть несколько ошибок.
Чтобы получить указатель на последний элемент списка, выполните:
Node **p = &head;
while (*p) {
p = &(*p)->next;
}
Ваш соответствующий код, т.е. ваша функция без элементов удаления, выглядит следующим образом:
while ((*list)->next != NULL) {
list = NEXT(*list);
}
Вы должны выполнить итерацию while (*list)
. Идея проверки next
, вероятно, вытекает из аналогичного кода, который использует указатель узла для итерации. Когда вы используете указатель на указатель узла, разыменование этого указателя имеет тот же эффект, что и доступ к next
, поскольку этот указатель сначала указывает на головной узел и на элемент next
предыдущего узла на последующих итерациях.
Вот почему вы должны назначить адрес от (*list)->next
до list
, когда вы хотите продвинуть указатель. (Компилятор предупреждает вас, что типы указателей не совпадают.)
Таким образом, «raw» l oop должно быть:
while (*list != NULL) {
list = &NEXT(*list);
}
Теперь давайте посмотрим на удаление. Когда вы определили, что узел должен быть удален, вы делаете:
LIST *node = list;
list = &(NEXT(*node));
free(DATA(*node));
free(*node);
Здесь вы не хотите перемещать указатель итератора. Вместо этого вы хотите обновить то, на что он указывает: вы хотите пропустить текущий узел *list
, отклонив указатель, который указывает на узел, на следующий узел или на NULL
, когда это был последний узел:
*list = NEXT(*node);
Когда вы это сделаете, list
и node
останутся с тем же адресом, изменилось только содержимое. (Поскольку node == list
, *node
теперь указывает на узел после узла, который вы хотите удалить, и вы случайно освободили этот узел и его данные. Сделайте временный указатель простым указателем на узел:
LIST node = *list;
*list = NEXT(node);
free(DATA(node));
free(node);
Помещение все вместе:
void DeleteFuncNotPermanent(LIST *list, int c)
{
while (*list)
{
if (((FUNC*) DATA(*list))->permament == FALSE)
{
LIST node = *list;
*list = (NEXT(*list));
free(DATA(node));
free(node);
}
else
{
list = &NEXT(*list);
}
}
}