Почему эта инициализация связанного списка не работает? - PullRequest
0 голосов
/ 24 мая 2018

Я пытаюсь инициализировать (или создать) связанный список с пустым узлом, указывающим на NULL, но он возвращает ошибку, и я не знаю почему.Кто-нибудь может мне помочь?

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

struct node {
    int times;
    char name[100];
    char number[100];  
    struct node* next;
};

typedef struct node* node;

void mklist(node* n) {
    (*n)->times = 0;
    strcpy((*n)->name, "null");
    strcpy((*n)->number, "null");
    (*n)->next = (node)NULL;
}

int main(void) {
    node n;
    mklist(&n);
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Вы можете легко сделать это в глобальной области видимости:

// nil = &nilObj, which means nil->next == nil.
// 
// This way, there's no checking for both 'nil' and 'NULL'!
// 
// As a consequence of this last point, you can make passing 'NULL'
// to most list functions invalid: it just means the user didn't
// use mklist() on every list they needed to manually work with.
static struct node nilObj = { 0, "null", "null", &nilObj };
node nil = &nilObj;

void mklist(node *n)
{
    *n = nil;
}

Как упоминал Стивен Доци, использование typedef T *Tname; обычно является плохой идеей, поскольку скрывает тот факт, что вы используете указатель, которыйможет сбивать с толку, когда вы используете Tname *n как (*n)->foo (я бы честно предположил, что вы используете n->foo).Некоторые API-интерфейсы делают это, но они делают это таким образом, чтобы выражать, что переменная является указателем на объект, а не на объект: вместо Node используется что-то вроде NodeRef или NodePtr, означающее в именичто это указатель на узел, а не узел.Apple Core Foundation API использует такие имена (например, CFStringRef).Я настоятельно рекомендую принять конвенцию, подобную этой, впредь.Приведенный выше код, который я разместил, может выглядеть примерно так:

static struct node nilObj = { 0, "null", "null", &nilObj };
nodeRef nil = &nilObj;

void mklist(nodeRef *n)
{
    *n = nil;
}
0 голосов
/ 24 мая 2018

Так что node на самом деле является указателем на struct node, очень запутанно

typedef struct node* node;

В main() вы объявляете указатель и передаете указатель на указатель на mklist()

node n;
mklist(&n);

В mklist(), n на самом деле является указателем на указатель на структуру, поэтому при разыменовании вы получаете указатель на структуру

void mklist(node* n){
    (*n)->times=0;

, но нигде в вашем кодеВы выделили память для фактической структуры.

Самое простое исправление того, как ваш код в настоящее время состоит в добавлении malloc()

void mklist(node* n) {
    *n = malloc(sizeof(*(*n)));
    // check for malloc() failure

    (*n)->times = 0;
    strcpy((*n)->name, "null");
    strcpy((*n)->number, "null");
    (*n)->next = (node)NULL;
}
...