C: функция делает удаление узла в общем c связанном списке - PullRequest
1 голос
/ 16 апреля 2020

У меня проблемы с написанием функции, которая удалит узел в общем c связанном списке.

Мой связанный список объявлен следующим образом (именно так мой профессор хочет, чтобы мы это делали):

typedef enum _STATUS {ERROR,OK} STATUS;
typedef enum _BOOLEAN {FALSE, TRUE} BOOLEAN;

#define MAX_NOME 20


typedef struct _FUNC
{
    char name[MAX_NOME];
    char dept[MAX_NOME];
    BOOLEAN permanent;
} FUNC;


typedef struct _LIST_NODE
{
    void * data;
    struct _LIST_NODE * next;
} LIST_NODE;


typedef LIST_NODE * LIST;

#define DATA(node) ((node)->data)
#define NEXT(node) ((node)->next)

Я пришел с этой функцией, чтобы удалить все узлы с постоянным = = ЛОЖЬ, но это действительно не работает.

void DeleteFuncNotPermanent(LIST *list)
{

    LIST *node = list;

    while ((*list)->next != NULL)
    {
        if(((FUNC*)DATA(*list))->permament == FALSE)
        {
            node = list;
            list = &(NEXT(*node));

            free(DATA(*node));
            free(*node);

        }
        else
        {
            list = NEXT(*list);
        }
    }
}

Любая обратная связь будет принята с благодарностью. Спасибо.

Ответы [ 2 ]

0 голосов
/ 16 апреля 2020

Я попытался переписать вашу функцию удаления. Дайте мне знать, если это работает. Изменения в основном связаны с разыменованием указателя.

void DeleteFuncNotPermanent(LIST *list)
{

    LIST *node = list;

    while (list!= NULL)    // change
    {
        if(((FUNC*)(DATA(list)))->permament == FALSE)   // change
        {
            node = list;
            list = NEXT(node);  //change

            free((FUNC*)(DATA(node)));  // change
            free(node);       // change

        }
        else
        {
            list = NEXT(list);    //change
        }
    }
}


0 голосов
/ 16 апреля 2020

Вы просматриваете список с указателем на указатель узла, что является хорошей идеей. (Однако указывать тип указателя 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);
        }
    }
}
...