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

C语言链表中间插入、遍历显示、指定位置删除功能异常

C语言链表实现增删打印功能异常修复

异常现象

  • 异常1:依次调用头插addAtfront、尾插addAtback、位置2插入addInbetween函数时,输入完中间节点名称后程序直接终止,无法执行后续显示、删除逻辑,异常输出如下:
--------------------------------
-----------Cake Shop------------
--------------------------------
First cake: First
Second cake : Second
Between cake : Between


...Program finished with exit code 0
Press ENTER to exit console.
  • 异常2:额外增加一次addAtfront、addAtback调用后,程序可运行至显示、删除流程,但中间插入节点位置错误,删除非头节点时会出现链表节点丢失错位问题,异常输出如下:
--------------------------------
-----------Cake Shop------------
--------------------------------
First cake: First1
First cake: First2
Second cake : Second1
Second cake : Second2
Between cake : Middle
List of cakes
First2
First1
Second1
Second2
Middle

Deleting cake at position 1: 
Present of now:
List of cakes
First1
Second1
Second2
Middle

问题根因

所有异常均来自3个核心功能函数的逻辑错误:

  1. 中间插入函数addInbetween遍历逻辑错误
    • 循环终止条件写为count<=pos,比正确遍历逻辑多走1个节点:当链表仅2个节点(头+尾)时,遍历结束后指针zig会走到NULL位置,后续执行zig->next直接触发空指针解引用,导致程序崩溃,是第一个异常的直接原因
    • 即使链表长度足够不触发崩溃,多走1步也会让插入位置偏移1位,直接把新节点插到目标位置的后方,甚至链表尾部,对应第二个异常里中间节点出现在链表最后的问题
  2. 删除函数delete逻辑错误
    • 空链表判断逻辑错误:判断条件写为head == NULL,但head是传入的二级指针(存储头指针变量的地址),永远不会为空,正确判断应该是*head == NULL
    • 非头节点删除时断链:找到待删除节点后,直接将前驱节点的next设为NULL,没有连接待删除节点的后继节点,导致待删除节点后的所有节点全部丢失,引发链表错位
  3. 打印函数display格式错误
    • 表头字符串List of cakes写在循环内部,每打印一个节点就会重复输出一次表头
    • 节点名称输出后未加换行,所有内容会挤在同一行,格式混乱

修复后完整代码

#include <stdio.h>
#include <stdlib.h>
struct FlavorList{
    char name[100];
    struct FlavorList* next ; 
};

void addAtfront(struct FlavorList **head){
    struct FlavorList *new_cake = (struct FlavorList*)malloc(sizeof(struct FlavorList));
    printf("First cake: ");
    scanf("%s",new_cake->name);
    new_cake->next = *head ; 
    *head = new_cake ; 
}

void addAtback(struct FlavorList **head){
    struct FlavorList* new_cake = (struct FlavorList*) malloc(sizeof(struct FlavorList)); 
    printf("Second cake : ");
    scanf("%s",new_cake->name);
    new_cake->next = NULL;
    struct FlavorList *last = *head;  
    if (*head == NULL){
       *head = new_cake;
       return;    
    } 
    while (last->next != NULL)
        last = last->next;
    last->next = new_cake;
    return;   
}

void addInbetween(struct FlavorList  ** head , int pos){
    struct FlavorList * new_cake = (struct FlavorList *) malloc(sizeof(struct FlavorList ));
    printf("Between cake : ");
    scanf("%s",new_cake->name);
    new_cake->next = NULL;
    // 位置合法性判断
    if(pos < 1){
        free(new_cake);
        printf("Invalid position\n");
        return;
    }
    // 插入位置为1直接复用头插逻辑
    if(pos == 1){
        new_cake->next = *head;
        *head = new_cake;
        return;
    }
    struct FlavorList  *zig = *head ; 
    int count = 1 ; 
    // 遍历到待插入位置的前驱节点(第pos-1个节点)即停止
    while(zig!=NULL && count < pos-1){
        count ++ ; 
        zig=zig->next ; 
    }
    // 位置超出链表长度容错处理
    if(zig == NULL){
        free(new_cake);
        printf("Position out of range, add to back\n");
        addAtback(head);
        return;
    }
    new_cake->next = zig->next ; 
    zig->next = new_cake ; 
}

void delete(struct FlavorList **head, int pos){
    // 正确判断空链表
    if(*head == NULL){
        printf("List is empty");
        return;
    }
    struct FlavorList*current=*head;
    struct FlavorList*previous=*head;
    if (pos==1){
        *head=current->next;
        free(current);
        current=NULL;
    }
    else{
        while(pos!=1){
            previous=current;
            current=current->next;
            pos--;
            // 位置越界容错
            if(current == NULL){
                printf("Position out of range\n");
                return;
            }
        }
        // 连接后继节点,避免断链
        previous->next=current->next;
        free(current);
        current=NULL;
    }
}

void display(struct FlavorList  **head){
    struct FlavorList  *zig = * head ;
    printf("List of cakes\n");
    while(zig != NULL){
        printf("%s\n",zig->name);
        zig=zig->next; 
    }
    printf("\n");
}

int main(){
    struct FlavorList *head = NULL ; 
    printf("--------------------------------\n");
    printf("-----------Cake Shop------------\n");
    printf("--------------------------------\n");
    addAtfront(&head);
    addAtback(&head);
    addInbetween(&head,2);
    display(&head);
    printf("Deleting cake at position 1: \n");
    delete(&head,1);
    printf("Present of now:\n");
    display(&head);
    return 0;
}

修复验证

第一个测试场景(头插+尾插+位置2插入)运行输出符合预期:

--------------------------------
-----------Cake Shop------------
--------------------------------
First cake: First
Second cake : Second
Between cake : Between
List of cakes
First
Between
Second

Deleting cake at position 1: 
Present of now:
List of cakes
Between
Second

内容的提问来源于stack exchange,提问作者Sahayog Shrestha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:16:07