Передача указателя на связанный список из функции-заполнителя не работает - PullRequest
0 голосов
/ 26 июля 2011

Я бездельничаю с указателями и структурами. Я хочу добиться следующего: (1) определить связанный список со структурой (numberRecord) (2) написать функцию, которая заполняет связанный список некоторыми примерами записей, пройдя через цикл (fillList) (3) подсчитать количество элементов в связанном списке (4) распечатать количество элементов

Сейчас я так далеко, что функция fillList работает хорошо, но мне не удается передать заполненный связанный список указателю в main (). В приведенном ниже коде функция printList отображает только одну запись, которая была добавлена ​​в main (), вместо отображения списка, созданного в функции fillList.


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

typedef struct numberRecord numberRecord;

//linked list
struct numberRecord {
             int number;
        struct numberRecord *next;
};

//count #records in linked list
int countList(struct numberRecord *record) {

         struct numberRecord *index = record;
    int i = 0;

    if (record == NULL)
        return i;

    while (index->next != NULL) {
        ++i;
        index = index->next;
    }

    return i + 1;
}

//print linked list
void printList (struct numberRecord *record) {

    struct numberRecord *index = record;

    if (index == NULL)
        printf("List is empty \n");

    while (index != NULL) {

        printf("%i \n", index->number);
        index = index->next;
    }

}

//fill the linked list with some sample records
void fillList(numberRecord *record) {

    numberRecord *first, *prev, *new, *buffer;

//as soon as you add more records you get an memory error, static construction
    new = (numberRecord *)malloc(100 * sizeof(numberRecord));
    new->number = 0;
    new->next = NULL;

    first = new;
    prev = new;
    buffer = new;

    int i;

    for (i = 1; i < 11; i++) {

        new++;

        new->number = i;
        new->next = NULL;

        prev->next = new;
        prev = prev->next;
    }

    record = first;
}


int main(void) {

    numberRecord *list;
    list = malloc(sizeof(numberRecord));
    list->number = 1;
    list->next = NULL;

    fillList(list);
    printf("ListCount: %i \n", countList(list));
    printList(list);
    return 0;
}

РЕШЕНИЕ Читайте посты ниже, они указали это решение и содержат некоторые очень проницательные замечания по поводу указателей. Ниже адаптированный код, который работает:

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

typedef struct numberRecord numberRecord;

//linked list
struct numberRecord {
             int number;
        struct numberRecord *next;
};

//count #records in linked list
int countList(struct numberRecord *record) {

         struct numberRecord *index = record;
    int i = 0;

    if (record == NULL)
        return i;

    while (index->next != NULL) {
        ++i;
        index = index->next;
    }

    return i + 1;
}

//print linked list
void printList (struct numberRecord *record) {

    struct numberRecord *index = record;

    if (index == NULL)
        printf("List is empty \n");

    while (index != NULL) {

        printf("%i \n", index->number);
        index = index->next;
    }

}

//fill the linked list with some sample records
 numberRecord *fillList() {

    numberRecord *firstRec, *prevRec, *newRec;

    int i;

    for (i = 1; i < 11; i++) {

        newRec = malloc(sizeof(numberRecord));
        newRec->number = i;
        newRec->next = NULL;

        //initialize firstRec and prevRec with newRec, firstRec remains head
        if (i == 1) {
            firstRec = newRec;
            prevRec = newRec;
        }
        prevRec->next = newRec;
        prevRec = prevRec->next;
    }

    return firstRec;
}


int main(void) {

    numberRecord *list;
    list = fillList();

    printf("ListCount: %i \n", countList(list));
    printList(list);
    return 0;
}

1 Ответ

2 голосов
/ 26 июля 2011

Это утверждение в fillList

record = first;

не влияет на переменную list в main. Указатели передаются по значению (как и все остальное) в C. Если вы хотите обновить переменную list в main, вам придется либо передать на нее указатель (&list) и соответственно изменить fillList, либо вернуть numberRecord* из fillList. (Я бы на самом деле пошел с этим вторым вариантом.)

Вот (плохая) иллюстрация:

Когда main вызывает fillList, в начальной точке этой функции указатели выглядят следующим образом:

main        memory       fillList
list ----> 0x01234 <----  record

Чуть позже, в fillList, вы выделяете некоторое хранилище для new (на самом деле это плохое имя, оно конфликтует с оператором в C ++, вводит людей в замешательство)

main        memory       fillList
list ----> 0x01234 <----  record
           0x03123 <----  new

В последней строке fillList у вас осталось:

main        memory       fillList
list ----> 0x01234   ,--  record
           0x03123 <----  new

record и list не являются одной и той же переменной. Они начинаются с одинакового значения, но изменение record не изменит list. Тот факт, что они оба указатели, ничем не отличается от, скажем, int s в этом отношении.

Вы можете изменить вещь , указанную на по списку в fillList, но вы не можете изменить то, что list указывает на (с вашей версией кода).

Самый простой способ обойти это изменить fillList следующим образом:

numberRecord *fillList() {
  ....
  return new;
}

А в main не выделяйте list напрямую, просто позвоните fillList(), чтобы инициализировать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...