我正在学习如何制作一个链表,但它没有打印出任何东西,我无法弄清楚为什么???请帮忙。我相信它与我的指针有关,但我不知道它是什么。
#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
按任意键继续
答案 0 :(得分:1)
这是因为你正在向你的函数传递一个空指针,并且退出循环的条件是该指针为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)
答案 1 :(得分:1)
在for循环中
for(int i = 0; i<3; i++){
addFirst(head, i);
}
你创建了一堆指向NULL
的指针。 head
永远不会改变,因为指针本身被传递&#34;由值&#34;。例如。 head
被复制,addFirst
中对指针本身的所有修改都在外面不可见。
这与说int
相同。想象一下void foo(int x);
。无论这个函数对x做什么都不在外面看。
然而,link ptr
指向的内存的变化当然是可见的。
E.g。这条线什么都不做:
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
。这是指向第一个节点的指针。当你想修改头部时,你发现它不是一个节点&#34;。这是另一回事。这是一个&#34;名称&#34;对于列表中的第一个节点。此名称本身是指向节点的指针。了解head
的内存布局与列表本身的不同之处。
head[8 bytes]->node1[16 bytes]->node2[16 bytes]->...->nodek[16 bytes]->NULL;
顺便说一下 - 这里唯一有词汇名称的是head
。所有节点都没有名称,可通过node->next
语法访问。
您还可以想象另一个指针link last
,它将指向nodek
。同样,这将与节点本身具有不同的内存布局。如果你想在函数中修改它,你需要传递给它的函数指针(例如指向指针)。
它指向的指针和数据是不同的东西。在你的脑海里,你需要将它们分开。指针类似于int
或float
。它通过&#34;按价值&#34;功能。是link ptr
已经是指针,允许您更新它指向的数据。但是,指针本身是按值传递的,并且指针(在您的情况下为ptr=tmp
)的更新在外部不可见。
(*ptr).next=xxx
,因为数据已更新(不是指针)。这意味着你需要做一个额外的步骤 - 在函数外部对指针进行更改,例如将指针本身(head
)转换为另一个指针的数据,例如使用struct node **ptr
(这里的第一个星说这是指向一个节点的指针,第二个星指针将该指针转换为另一个指针的数据。