C语言实现带增删改查功能的链表时appendNode崩溃、显示乱码求助
问题原因与修复方案
核心根本原因
你代码里的所有Node节点都声明为函数内的局部栈变量,函数执行结束后栈空间会被系统自动回收,你存储的节点指针全部变成野指针,访问非法内存就会触发崩溃、输出垃圾值等问题。
对应你遇到的两个问题的具体触发逻辑
- appendNode执行崩溃:
createFirst函数中创建的首节点是该函数的栈局部变量,createFirst执行结束后节点内存被回收,start指向无效内存,appendNode中解引用*start触发非法访问直接崩溃。 - 只创建首节点display输出垃圾值:首节点栈内存被后续函数调用的栈数据覆盖,存储的
data值被篡改,所以输出乱码。
其他存在的逻辑错误
- 插入节点的位置校验逻辑完全错误,原有
if(n>count || n<count)的判断等于仅允许n等于count,不符合插入逻辑 - 删除节点的逻辑错误,仅修改了局部变量的值,没有修改链表的指针指向,也没有释放内存
- 遍历链表用值拷贝而非指针遍历,逻辑完全错误
- 主函数返回值应该为
int而非void
完整修复代码
#include <stdio.h> #include <stdlib.h> void createFirst(int); void appendNode(int); void insertFirst(int); void insertNode(int,int); void deleteFirst(); void deleteNode(int); void display(); struct Node { int data; struct Node *link; }; typedef struct Node Node; Node *start = NULL; int count=0; // 新增公共节点创建函数,用malloc分配堆内存,生命周期手动控制 Node* createNode(int d) { Node* node = (Node*)malloc(sizeof(Node)); node->data = d; node->link = NULL; return node; } int main() { int ch; do { printf("\n"); printf("1. Create the list \n"); printf("2. Insert an element at any position \n"); printf("3. Delete an element at any position \n"); printf("4. Display the list \n"); printf("5. Quit \n"); printf("Enter your choice : \n"); scanf("%d",&ch); switch(ch) { case 1: { int a; char c; printf("Enter the data : \n"); scanf("%d",&a); createFirst(a); while(1) { printf("Do you want to continue[Y/N] : \n"); scanf(" %c",&c); if(c=='Y' || c=='y') { printf("Enter the data : \n"); scanf("%d",&a); appendNode(a); } else if(c=='N' || c=='n') { break; } else { continue; } } break; } case 2: { int a,pos; char c; printf("Enter the data : \n"); scanf("%d",&a); printf("Enter the position : \n"); scanf("%d",&pos); if(pos == 1) { insertFirst(a); } else { insertNode(pos,a); } while(1) { printf("Do you want to continue[Y/N] : "); scanf(" %c",&c); if(c=='N' || c=='n') { break; } if(c!='Y' && c!='y') { continue; } printf("Enter the data : \n"); scanf("%d",&a); printf("Enter the position : \n"); scanf("%d",&pos); if(pos == 1) { insertFirst(a); } else { insertNode(pos,a); } } break; } case 3: { int pos; char c; printf("Enter the position : \n"); scanf("%d",&pos); if(pos == 1) { deleteFirst(); } else { deleteNode(pos); } while(1) { printf("Do you want to continue[Y/N] : "); scanf(" %c",&c); if(c=='N' || c=='n') { break; } if(c!='Y' && c!='y') { continue; } printf("Enter the position : \n"); scanf("%d",&pos); if(pos == 1) { deleteFirst(); } else { deleteNode(pos); } } break; } case 4: { display(); break; } case 5: { // 退出前释放所有节点内存避免泄漏 while(start != NULL) { Node* del = start; start = start->link; free(del); } return 0; } default: { printf("Invalid choice \n"); break; } } }while(ch!=5); return 0; } void createFirst(int d) { start = createNode(d); count++; } void appendNode(int d) { Node* temp = start; while(temp->link != NULL) { temp = temp->link; } temp->link = createNode(d); count++; } void insertFirst(int d) { Node* newnode = createNode(d); newnode->link = start; start = newnode; count++; } void insertNode(int n,int d) { // 修正位置校验逻辑,插入位置合法范围是1到count+1 if(n<1 || n>count+1) { printf("Invalid position \n"); return; } Node* temp = start; int i; for(i=1;i<n-1;i++) { temp = temp->link; } Node* newnode = createNode(d); newnode->link = temp->link; temp->link = newnode; count++; } void deleteFirst() { if(start != NULL) { Node* del = start; printf("Deleted element : %d \n", del->data); start = del->link; free(del); count--; } else { printf("Underflow \n"); } } void deleteNode(int n) { // 修正删除位置校验逻辑,删除位置合法范围是1到count if(n<1 || n>count) { printf("Invalid position \n"); return; } Node* temp = start; int i; for(i=1;i<n-1;i++) { temp = temp->link; } Node* del = temp->link; printf("Deleted node : %d\n", del->data); temp->link = del->link; free(del); count--; } void display() { if(start == NULL) { printf("The list is empty \n"); return; } Node* temp = start; while(temp != NULL) { printf("%d ", temp->data); temp = temp->link; } printf("\n"); }
内容的提问来源于stack exchange,提问作者Surya Majumder
相关产品推荐
相关产品推荐

