Не удалось реализовать связанный список в C - PullRequest
1 голос
/ 29 апреля 2020

Я не понимаю, почему эта программа не работает и элементы не были вставлены в список, как предполагалось.

Каждый раз, когда я отлаживаю, я вижу, что когда я go к main метод после метода «insert», связанный список по-прежнему пуст, и я не понимаю, почему, потому что я думаю, что это должно быть хорошо, потому что я использую указатели (Это похоже на случай «Dangling Pointer», но если это так, Я не понимаю, почему).

Может быть, я должен использовать двойную звезду (**)? Если да, то почему в массивах это не имеет значения?

Вот исходный код:

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

struct A{
    int val;
    struct A* next;
} A;

void insert(struct A* L, int newVal) {

    if (L == NULL) {

        L = (struct A*) malloc(sizeof(struct A));
        L->val = newVal;
        L->next = NULL;
    }

    else {

        struct A* p = L;

        while (p->next != NULL) {

            p = p->next;
        }

        p->next = (struct A*) malloc(sizeof(struct A));
        p->next->val = newVal;
        p->next->next = NULL;
    }
}


void printA(struct A* printed) {

    struct A* p = printed;

    while (p != NULL) {
        printf("%d\n", p->val);
        p = p->next;
    }
}


int main() {

    struct A* L = NULL;

    insert(L, 1);
    printf("1 success\n");

    insert(L, 2);
    printf("2 success\n");

    insert(L, 3);
    printf("3 success\n");

    insert(L, 4);
    printf("4 success\n");

    insert(L, 5);
    printf("5 success\n");

    printf("\n\n\n");

    printA(L);

    return 0;
}

Спасибо.

1 Ответ

2 голосов
/ 29 апреля 2020

insert Первый аргумент функции - это указатель на структуру. Когда вы передаете свою структуру, insert получает адрес и создает локальный указатель на то же место. Чтобы изменить то, на что указывает фактическая структура (из main), вы должны передать двойной указатель.

Ниже приведены части, которые необходимо изменить:

void insert(struct A** L, int newVal) {

    if (*L == NULL) {

        *L = (struct A*) malloc(sizeof(struct A));
        (*L)->val = newVal;
        (*L)->next = NULL;
    }

    else {

        struct A* p = *L;

        ...
        ...
        ...
    }
}    

int main() {

    struct A* L = NULL;

    insert(&L, 1);
    printf("1 success\n");

    ...
    ...
    ...

    printA(L);

    return 0;
}

Другой подход заключается в том, чтобы остаться с одним указателем, но изменить возвращаемое значение от insert до struct A*. Вам просто нужно присвоить возвращаемое значение вашей main struct, например:

struct A *insert(struct A* L, int newVal) {

    if (L == NULL) {

        L = (struct A*) malloc(sizeof(struct A));
        L->val = newVal;
        L->next = NULL;

        return L;
    }

    else {
        ...
    }

    return L;
}

int main() {

    struct A* L = NULL;

    L = insert(L, 1);
    ...
    return 0;
}

Кроме того, ваша функция печати никуда не движется. Добавить строку p = p->next;

void printA(struct A* printed) {

    struct A* p = printed;

    while (p != NULL) {
        printf("%d\n", p->val);
        p = p->next;
    }
}
...