You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

链表创建与显示异常:仅输出最后两个节点值,指针遭意外修改

问题分析与解决方案

哈哈,这个问题我刚学链表的时候也踩过一模一样的坑!核心原因是你误用了指向指针的指针来遍历链表,直接把原本的头指针(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:28:15