Глава связанного списка не может указывать на старый элемент - PullRequest
0 голосов
/ 16 февраля 2019

У меня есть этот код, и я пытаюсь создать односвязный список.Однако каждый раз, когда я добавляю новый элемент в начало, мой код не может указать элемент в начале списка на старый элемент.

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

struct list {
    struct node* head;
};

struct node {
    int data;
    struct node* next;
};

struct list* list_init(void) {
    struct list *l;
    l = malloc(sizeof(struct list));
    if (l == NULL) {
        return 1;
    }
    else {
        l -> head = NULL;
        return l;
    }

}

struct node* new_node(int num) {
    struct node *n;
    n = malloc(sizeof(struct node));
    if (n == NULL) {
        return NULL;
    }
    else {
        n -> data = num;
        n -> next = NULL;
        return n;
    }
}

int list_add_front(struct list* l, struct node* n) {
    if (l == NULL) {
        return 1;
    }
    else {
        if (l -> head == NULL) {
            // Make sure that the list head points to this node.
            l -> head = &n;
        }
        // Make list head point to new node;
        // Make new node point to old head node;
        else {
            struct node* old_head = l -> head;

            n->next = old_head;

            l -> head = &n; 
        }
    }
}

int main()
{
    struct list* l = list_init();
    struct node* nn = new_node(2);

    printf("l address: %p \n", l);
    printf("n address: %p \n", nn);

    list_add_front(l, nn);
    int* datapoint = (l->head)->data;

    printf("List head data at first: %i, on address %p. \n\n", *datapoint, datapoint);

    struct node* nn2 = new_node(12);

    printf("l address: %p \n", l);
    printf("nn2 address: %p \n", nn2);

    list_add_front(l, nn2);
    int* datapoint3 = (l->head) -> data; 
    printf("List head data is now: %i, on address %p. \n\n", *datapoint3, datapoint3);

    struct node* nextnode = (l->head) -> next;
    printf("it points to address %p, which is the list itself. why?? . \n\n", nextnode);



}

Не знаю почему.Это не так в list_add_front Я верю.Я не понимаю, как он связывается с адресом самой структуры списка, так как печать указателя, кажется, отдает это.

Вот исполняемый код онлайн, для удобства может быть: https://onlinegdb.com/rk7_meISN

Заранее всем спасибо.

1 Ответ

0 голосов
/ 16 февраля 2019

Как указал dbush, у вас есть ряд предупреждений, которые необходимо исправить.Обязательно скомпилируйте с -Wall

В частности, в list_add_front измените все &n на n.Это должно решить проблему.Компилятор должен / должен пометить это.

С &n это указатель на указатель struct node, а не указатель на struct node [что вам нужно],Использование &n указывает на адрес из n, который находится в программном стеке, а не , на что указывает n.

Вот аннотированныйи исправленная версия.Он использует:

#if 0
// original code ..
#else
// fixed code ...
#endif

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

struct list {
    struct node *head;
};

struct node {
    int data;
    struct node *next;
};

struct list *
list_init(void)
{
    struct list *l;

    l = malloc(sizeof(struct list));
    if (l == NULL) {
#if 0
        return 1;
#else
        return l;
#endif
    }
    else {
        l->head = NULL;
        return l;
    }

}

struct node *
new_node(int num)
{
    struct node *n;

    n = malloc(sizeof(struct node));
    if (n == NULL) {
        return NULL;
    }
    else {
        n->data = num;
        n->next = NULL;
        return n;
    }
}

int
list_add_front(struct list *l, struct node *n)
{
    if (l == NULL) {
        return 1;
    }
    else {
        if (l->head == NULL) {
            // Make sure that the list head points to this node.
#if 0
            l->head = &n;
#else
            l->head = n;
#endif
        }

        // Make list head point to new node;
        // Make new node point to old head node;
        else {
            struct node *old_head = l->head;
            n->next = old_head;
#if 0
            l->head = &n;
#else
            l->head = n;
#endif
        }
    }
}

int
main()
{
    struct list *l = list_init();
    struct node *nn = new_node(2);

    printf("l address: %p \n", l);
    printf("n address: %p \n", nn);

    list_add_front(l, nn);
#if 0
    int *datapoint = (l->head)->data;
#else
    int *datapoint = &l->head->data;
#endif

    printf("List head data at first: %i, on address %p. \n\n",
        *datapoint, datapoint);

    struct node *nn2 = new_node(12);

    printf("l address: %p \n", l);
    printf("nn2 address: %p \n", nn2);

    list_add_front(l, nn2);
#if 0
    int *datapoint3 = (l->head)->data;
#else
    int *datapoint3 = &l->head->data;
#endif

    printf("List head data is now: %i, on address %p. \n\n",
        *datapoint3, datapoint3);

#if 0
    struct node *nextnode = (l->head)->next;
#else
    struct node *nextnode = l->head->next;
#endif

    printf("it points to address %p, which is the list itself. why?? . \n\n",
        nextnode);

#if 1
    return 0;
#endif
}
...