链表创建与显示异常:仅输出最后两个节点值,指针遭意外修改
问题分析与解决方案
哈哈,这个问题我刚学链表的时候也踩过一模一样的坑!核心原因是你误用了指向指针的指针来遍历链表,直接把原本的头指针(start1/start2)给修改了,导致后续访问丢失了前面的节点。咱们一步步拆解清楚:
1. 为什么temp会修改start1/start2?
你在create_node和display里都用了struct node **temp = s1;(或s),这里的temp是一个指向指针的指针,它直接指向start1这个变量本身。当你执行(*temp) = (*temp)->next;时,本质是在修改start1的值——把start1从指向链表的第一个节点,一步步移到了后面的节点(甚至最后变成NULL)。
举个例子:
- 在
create_node里创建第三个节点时,遍历过程中(*temp) = (*temp)->next会把start1改成第二个节点的地址,虽然第三个节点成功挂到链表上,但start1已经不再指向第一个节点了! - 在
display函数里,遍历完整个链表后,start1/start2会被改成NULL,下次再调用display就什么都输出不了了。
2. 修正方案:用普通节点指针遍历
遍历链表时,只需要用一个普通的节点指针(struct node *temp)来临时保存当前遍历的位置,这样修改temp不会影响原本的头指针。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> // 必须包含malloc/exit需要的头文件 #include <conio.h> // 对应clrscr()和getch()的头文件 struct node { int info; struct node *next; } *start1 = NULL, *start2 = NULL; void create_node(struct node **s1); void display(struct node **s); void create_node(struct node **s1) { struct node *ptr = NULL, *temp = *s1; // 换成普通节点指针,指向头节点 ptr = (struct node *)malloc(sizeof(struct node)); // 新增:检查内存分配是否成功,避免空指针崩溃 if (ptr == NULL) { printf("Memory allocation failed!\n"); return; } if (*s1 == NULL) { *s1 = ptr; } else { // 用temp遍历,完全不修改原头指针 while (temp->next != NULL) temp = temp->next; temp->next = ptr; } ptr->next = NULL; printf("enter the value\n"); scanf("%d", &(ptr->info)); } void display(struct node **s) { struct node *temp = *s; // 普通节点指针,从头节点开始遍历 while (temp != NULL) { printf("%d\t", temp->info); temp = temp->next; // 移动临时指针,不影响原头指针 } } void main() { int choice = 0; while (1){ clrscr(); printf("enter your choice\n"); printf("enter 1 to create_node1\nenter 2 to create node 2 \nenter 3 to display node 1\nenter 4 to display node2\nenter 5 to exit\n"); printf("\n"); scanf("%d", &choice); switch (choice) { case 1: create_node(&start1); break; case 2: create_node(&start2); break; case 3: display(&start1); getch(); break; case 4: display(&start2); getch(); break; case 5: exit(1); break; default: printf("invalid"); } } }
3. 额外小提醒
- 记得包含
stdlib.h和conio.h,否则老编译器可能会报编译警告 - 内存分配后一定要检查是否成功,这是避免程序崩溃的好习惯
- 标准C里不推荐用
void main(),如果是现代编译器建议改成int main()并返回0,不过Turbo C这类老环境用void main()也没问题
内容的提问来源于stack exchange,提问作者user9181273
相关产品推荐
相关产品推荐

