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个核心功能函数的逻辑错误:
- 中间插入函数
addInbetween遍历逻辑错误- 循环终止条件写为
count<=pos,比正确遍历逻辑多走1个节点:当链表仅2个节点(头+尾)时,遍历结束后指针zig会走到NULL位置,后续执行zig->next直接触发空指针解引用,导致程序崩溃,是第一个异常的直接原因 - 即使链表长度足够不触发崩溃,多走1步也会让插入位置偏移1位,直接把新节点插到目标位置的后方,甚至链表尾部,对应第二个异常里中间节点出现在链表最后的问题
- 循环终止条件写为
- 删除函数
delete逻辑错误- 空链表判断逻辑错误:判断条件写为
head == NULL,但head是传入的二级指针(存储头指针变量的地址),永远不会为空,正确判断应该是*head == NULL - 非头节点删除时断链:找到待删除节点后,直接将前驱节点的
next设为NULL,没有连接待删除节点的后继节点,导致待删除节点后的所有节点全部丢失,引发链表错位
- 空链表判断逻辑错误:判断条件写为
- 打印函数
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
相关产品推荐
相关产品推荐

