C 插入到链接列表中

C 插入到链接列表中,c,C,我仍然在学习链表,并且一直在尝试创建一种方法来插入链表 我只是想知道这是不是正确的插入方式?另外,如何打印整个链接列表,使其打印类似于abc 以下是我所拥有的: struct node { char value; struct node *next; }; typedef struct node item; void main() { InsertChar('a'); InsertChar('b'); InsertChar('c'); } void In

我仍然在学习链表,并且一直在尝试创建一种方法来插入链表

我只是想知道这是不是正确的插入方式?另外,如何打印整个链接列表,使其打印类似于
abc

以下是我所拥有的:

struct node {
   char value;
   struct node *next;
};

typedef struct node item;

void main() {
    InsertChar('a');
    InsertChar('b');
    InsertChar('c');
}

void InsertChar(char s) {
    item *curr, *head;

    head = NULL;

    curr = (item *)malloc(sizeof(item));
    curr->value = s;
    curr->next = head;
    head = curr;

    while(curr) {
        printf("%c\n", curr->value);
        curr = curr->next;
    }
}

首先,您的函数
InsertChar
每次都会覆盖
head
的值(
head=curr
),因此您将得到一个包含一项的列表

您需要声明将存储
head
的内容

struct list
{
    struct node *head;
};
现在,通过浏览每个
节点
,您可以轻松打印
列表

void PrintList(struct list* list)
{
    struct node *curr = list->head;

    while (curr != NULL)
    {
        printf("%c\n", curr->value);
        curr = curr->next;
    }
}

现在您需要修改
InsertChar
,以便列表中的最后一项(您将如何找到它?)指向您的新项。我将把它留给您:)

您可能已经注意到,您无法从外部
InsertChar()
访问列表(如果有)。您不使用全局变量,也不输入或输出它

更好的实施:

item * InsertChar(item ** phead, char s) {
    item * curr;

    // First, allocate a new item and fill it.
    curr = malloc(sizeof(item)); // no need to cast here
    if (curr) { // only if malloc() succeeds
        curr->value = s;
        curr->next = *phead;
        *phead = curr;
    }
    return curr;
}

// InsertChar() is only supposed to insert, not to print.
void PrintList(item * head) {
    item * curr = head;   
    while(curr) {
        printf("%c", curr->value); // omit the line break as you want abc
        curr = curr->next;
    }
    printf("\n"); // now the line break
    return;
    // alternative implementation for while loop:
    for(curr=head; curr; curr=curr->next) {
        printf("%c\n", curr->value);
    }
}

void FreeList(item * head) {
    item * curr = head;   
    while(curr) {
        item * next = curr->next; // read it out before freeing.
        free(curr);
        curr = next;
    }
}
这样你现在就可以做了

int main() {
    item * list = NULL; // empty for now, no contents.
    char success = 1;
    success = success && InsertChar(&list, 'a');
    success = success && InsertChar(&list, 'b');
    success = success && InsertChar(&list, 'c');
    if (!success) {
        printf("Oops?");
        FreeList(list);
        return 1;
    }
    PrintList(list);
    FreeList(list); // clean up.
}
哎呀?我没有测试它,但在我看来,它打印的是“cba”。为什么会这样?好吧,InsertChar()将一切从头开始

怎么避开这个

我们可以创建一个AppendChar()函数。但这承担着我们陷入陷阱的危险:总是从一开始就开始寻找正确的地方。因此,我将指出另一种方法:

int main() {
    item * list = NULL; // empty for now, no contents.
    item * cursor = InsertChar(&list, 'a');
    if (!cursor) goto error;
    // cursor now contains our first entry.
    // We put the next one to cursor->next:
    cursor = InsertChar(&cursor->next, 'b');
    if (!cursor) goto error;
    cursor = InsertChar(&cursor->next, 'c');
    if (!cursor) goto error;
    PrintList(list);
    FreeList(list); // clean up.
    return 0;
  error:
    printf("Oops?");
    FreeList(list);
    return 1;
}
我不确定我是否正确(没有测试),但这应该是一条路


如果您是其中一个被教导在任何情况下goto都是邪恶的人,请随意以不同的方式实现错误处理。

您需要查看函数定义
void PrintList(struct list){…}
。您有一个类型
struct list
,但没有变量名(在原型中是OK,在函数定义中不是OK)。您应该能够使用
void PrintList(struct list*list){…}
,因为结构标记位于与普通变量名不同的命名空间中。