C - 简单链表无法打印



我正在学习如何制作链表,但它根本无法打印出任何东西,我不知道为什么???请帮忙。我相信这与我的指针有关,但我不知道它是什么。

#include <stdio.h>
#include <stdlib.h>
// typedef is used to give a data type a new name
typedef struct node * link ;// link is now type struct node pointer
/*
typedef allows us to say "link ptr"
instead of "struct node * ptr"
*/
struct node{
int item ;// this is the data
link next ;//same as struct node * next, next is a pointer
};
void printAll(link head); // print a linked list , starting at link head
void addFirst(link ptr, int val ); // add a node with given value to a list
link removeLast(link ptr); // removes and returns the last element in the link
//prints the link
void printAll(link head){
link ptr = head;
printf("nPrinting Linked List:n");
while(ptr != NULL){
printf(" %d ", (*ptr).item);
ptr = (*ptr).next;// same as ptr->next
}
printf("n");
}
//adds to the head of the link
void addFirst(link ptr, int val ){
link tmp = malloc(sizeof(struct node));// allocates memory for the node
tmp->item = val;
tmp->next = ptr;
ptr = tmp;
}
// testing
int main(void) {
link head = NULL;// same as struct node * head, head is a pointer type
//populating list
for(int i = 0; i<3; i++){
addFirst(head, i);
}
printAll(head);
return 0;
}

输出:

打印链表:

返回的进程 0 (0x0( 执行时间:0.059 s

按任意键继续

这是因为您将一个 null 指针传递给您的函数,并且退出循环的条件是该指针为 null,因此不会发生任何事情。 您的addFirst函数采用指针的值,但它不能修改您在 main(( 中声明的head。 若要修改head,需要传递指向链接的指针,然后可以取消引用该指针以访问head,然后可以对其进行更改。

void addFirst(link *ptr, int val ){
link tmp = malloc(sizeof(struct node));// allocates memory for the node
tmp->item = val;
tmp->next = *ptr;
*ptr = tmp;
}

现在,您可以更改头部指针。只需记住在调用函数时将地址传递给它。addFirst(&head,i)

在 for 循环中

for(int i = 0; i<3; i++){
addFirst(head, i);
}

您创建了一堆指向NULL的指针。head永远不会改变,因为指针本身是"按值"传递的。F.D.head被复制,并且对addFirst中的指针本身的所有修改在外部都不可见。

这与int相同。想象一下void foo(int x);.无论此函数对 x 做什么,在外面都是不可见的。

但是,link ptr指向的内存的变化当然是可见的。

例如,此行不执行任何操作:

tmp->next = ptr;
ptr = tmp;      <=== this line
}

您可以通过多种方式解决此问题。一种是从addFirst返回新节点,另一种是使link ptr成为指向指针的指针:link *ptr。由于在这种情况下您要更改指针值(而不是指针值(:

//link *ptr here a pointer to pointer
void addFirst(link * ptr, int val ){
link tmp = malloc(sizeof(struct node));// allocates memory for the node
tmp->item = val;
tmp->next = *ptr; //<<changed
*ptr = tmp;    //<<changed
}

不要忘记更新上面的声明。和电话:

void addFirst(link * ptr, int val ); // add a node with given value to a list
...
for(int i = 0; i<3; i++){
addFirst(&head, i);
}

然后此代码生成:

Printing Linked List:
2  1  0

补充:重要的是要了解使用链表需要处理两种不同类型的数据。

首先是struct node,您可以使用link传递这种类型的数据。

其次是head。这是指向第一个节点的指针。当您想修改头部时,您会发现它不是一个"节点"。这是另一回事。它是列表中第一个节点的"名称"。此名称本身就是指向节点的指针。了解head的内存布局与列表本身有何不同。

head[8 bytes]->node1[16 bytes]->node2[16 bytes]->...->nodek[16 bytes]->NULL;

顺便说一句 - 这里唯一有词法名称的是head.所有节点都没有名称,可通过node->next语法访问。

你也可以想象这里的另一个指针,link last它将指向nodek。同样,这将具有与节点本身不同的内存布局。如果你想在函数中修改它,你需要传递给函数指针(例如,指针到指针(。

指针和它指向的数据是不同的东西。在你的脑海中,你需要将它们分开。指针类似于intfloat。它"按值"传递给函数。是的,link ptr已经是指针,这允许您更新它指向的数据。但是,指针本身是按值传递的,并且对指针的更新(在您的情况下ptr=tmp(在外面不可见。

当然,(*ptr).next=xxx是可见的,因为数据已更新(而不是指针(。这意味着你需要做一个额外的步骤 - 使对指针的更改在函数之外可见,例如将指针本身(head(转换为另一个指针的数据,例如使用struct node **ptr(这里的第一个星表示这是指向节点的指针,第二个星号将该指针转换为另一个指针的数据。

相关内容

  • 没有找到相关文章

最新更新