Вставка нового узла в односвязный список не работает, когда я вызываю функцию в цикле - PullRequest
1 голос
/ 05 мая 2020

Я пытаюсь добавить узел в конец списка, поэтому я написал простую функцию append_node. Эта функция нормально работает, но когда я использую for l oop, дополнительный узел с undefined value сохраняется в головном узле .

Вот код:

int main() {
    linked_list *list;

    append_node(&list, 4);
    append_node(&list, 20);
    append_node(&list, 200);

    print_linked_list(list);    // 4 20 200
                                //prints just fine
}

код выше работает нормально, но когда я делаю это ниже:

int main() {
    linked_list *list;

    for (int i = 0; i < 5; i++)
        append_node(&list, i);

    print_linked_list(list);   // 11342689 0 1 2 3 4
                               // prints a extra undefined node here at the head 
}

ожидаемый результат: 0 1 2 3 4 фактический результат: 11342689 0 1 2 3 4

вот функция append_node:

void append_node(linked_list **head_ref, int value) {
    linked_list *current = *head_ref;

    linked_list *new_node = (linked_list *)malloc(sizeof(linked_list));
    new_node->node_value = value;
    new_node->next_node = NULL;

    if (*head_ref == NULL) {
        *head_ref = new_node;
        return;
    }

    while (current->next_node)
        current = current->next_node;

    current->next_node = new_node;
    return;
}

всякий раз, когда я использую loop, список получает новую голову с неопределенным значением . Остальная часть списка кажется правильной. Не знаю, почему это происходит. Кто-нибудь может мне сказать? Заранее спасибо :)

Ответы [ 3 ]

2 голосов
/ 05 мая 2020

Вы должны инициализировать linked_list *list как NULL, и все должно работать нормально.

1 голос
/ 05 мая 2020

Переменная list в main не инициализирована. В обоих случаях код имеет неопределенное поведение. Неопределенное поведение иногда приводит к ожидаемому поведению, иногда - нет. Код, сгенерированный для обеих функций, различается, поэтому возможно, что место, где хранится list, окажется нулевым указателем в первом случае, а не во втором.

Боюсь, что даже компилируйте ваш программа с включенными дополнительными предупреждениями (gcc -Wall -Wextra -Werror) не обнаружила бы эту ошибку.

Вот измененная версия:

#include <stdio.h>
#include <stdlib.h>

typedef struct linked_list {
    struct linked_list *next_node;
    int node_value;
} linked_list;

void print_linked_list(const linked_list *list) {
    while (list) {
        printf("%d ", list->node_value);
    }
    printf("\n");
}

linked_list *append_node(linked_list **head_ref, int value) {
    linked_list *current = *head_ref;
    linked_list *new_node = malloc(sizeof(linked_list));
    if (new_node) {
        new_node->node_value = value;
        new_node->next_node = NULL;
        if (current == NULL) {
            *head_ref = new_node;
        } else {
            while (current->next_node)
                current = current->next_node;
            current->next_node = new_node;
        }
    }
    return new_node;   // if memory allocation failed, the function will return NULL
}

int main() {
    linked_list *list = NULL;

    for (int i = 0; i < 5; i++)
        append_node(&list, i);

    print_linked_list(list);
    return 0;
}
1 голос
/ 05 мая 2020

Переменные с автоматической c продолжительностью хранения не инициализируются неявно. Si в этом объявлении

linked_list *list ;

объявлен указатель list с неопределенным значением.

В результате программа имеет неопределенное поведение.

Вы должны инициализировать указатель явно как

linked_list *list = NULL;

Кроме того, функцию append_node можно было бы определить проще и безопаснее, учитывая, что указатель list передается по ссылке на функцию.

Вот, пожалуйста.

int append_node( linked_list **head_ref, int value )
{
    linked_list *new_node = malloc( sizeof( linked_list ) );
    int success = new_node != NULL;

    if ( success )
    {
        new_node->node_value = value;
        new_node->next_node  = NULL;

        while ( *head_ref != NULL )
        {
            head_ref = &( *head_ref )->next_node;
        }

        *head_ref = new_node;
    }

    return success;
}
...