C语言链表实现餐厅管理软件时出现Segmentation Fault问题求助
解决基于链表的餐厅管理软件段错误问题
这段代码存在多个关键错误导致运行时触发Segmentation Fault,以下是问题拆解和修复方案:
核心错误点及修复
1. 未初始化的choice变量
main函数中int choice;未初始化,直接进入while(choice!=3)会读取栈上的垃圾值,导致程序初始行为异常。
修复:初始化choice为非3的值,比如:
int choice = 0;
2. insert_at_start链表操作逻辑错误
原代码在链表非空时会形成循环链表,触发遍历无限循环或段错误:
else{ node->next = head; head->next = node; }
正确的头插逻辑是让新节点指向原链表的第一个有效节点,再将哨兵节点head指向新节点,无需额外判断链表是否为空。
修复:
void insert_at_start(struct bill_item* node){ node->next = head->next; // 新节点衔接原第一个节点 head->next = node; // 哨兵节点指向新节点 }
3. customer_name野指针非法访问
book函数中node->customer_name是未分配内存的野指针,直接用fgets写入会访问非法内存,触发段错误。
修复:在创建节点后为客户名字分配内存:
struct bill_item* node = (struct bill_item*)malloc(sizeof(struct bill_item)); // 分配30字符+1个结束符的内存 node->customer_name = malloc(31 * sizeof(char));
4. display_list遍历逻辑错误
原循环条件while(ptr->next!=NULL)会跳过最后一个节点,且链表为空时ptr为NULL,访问ptr->next会触发段错误。
修复:将循环条件改为遍历所有有效节点:
void display_list(){ printf("\nBill No\t\tOrder Item\t\tCname\t\tQ\t\tTotal"); struct bill_item* ptr = head->next; // 直接指向第一个有效节点 while(ptr!=NULL){ printf("\n%d\t\t%d\t\t%s\t\t%d\t\t%.2f",ptr->bill_no,ptr->order_item_no,ptr->customer_name,ptr->quantity,ptr->total); ptr = ptr->next; } }
5. order_item_no未赋值
book函数中未给node->order_item_no赋值,打印时会输出垃圾值。
修复:选择菜品后直接赋值:
scanf("%d",&choice); node->order_item_no = choice; // 记录用户选择的菜品序号
6. fflush(stdin)的未定义行为
C标准中fflush(stdin)是未定义行为,不能用来清除输入缓冲区的换行,会导致输入逻辑异常。
修复:用getchar()循环吃掉缓冲区残留字符,替换所有fflush(stdin)为:
// 清除输入缓冲区的所有残留字符直到换行 while((getchar()) != '\n');
修复后的完整代码
#include<stdio.h> #include<stdlib.h> #include<string.h> struct items{ char *item_name; float cost; }; struct items array[] = { {"Pizza",49.9},{"Apples",22.0},{"Oranges",10.5},{"Grapes",3.5},{"Parotta",4.5} }; struct bill_item{ int bill_no; char* customer_name; int order_item_no; int quantity; float total; struct bill_item *next; }; struct bill_item* head; int count=0; void insert_at_start(struct bill_item* node); void insert_at_end(struct bill_item* node); void book(); void display_list(); int main(){ int choice = 0; head = (struct bill_item*)malloc(sizeof(struct bill_item)); head->next = NULL; while(choice!=3){ printf("\n----------------------------------------------"); printf("\n1.Book\t2.Check Orders\t3.Exit\nEnter option: "); scanf("%d",&choice); while((getchar()) != '\n'); // 清除缓冲区换行 printf("\n------choice %d",choice); switch(choice){ case 1: book(); printf("\nItem Purchased!!"); break; case 2: display_list(); break; case 3: break; default: printf("\nEnter the correct option"); break; } } // 释放链表内存,避免内存泄漏 struct bill_item* temp; while(head != NULL){ temp = head; head = head->next; if(temp->customer_name != NULL){ free(temp->customer_name); } free(temp); } return 0; } void insert_at_start(struct bill_item* node){ node->next = head->next; head->next = node; } void insert_at_end(struct bill_item* node){ struct bill_item* ptr = head; while(ptr->next!=NULL){ ptr = ptr->next; } ptr->next = node; } void book(){ char c; struct bill_item* node = (struct bill_item*)malloc(sizeof(struct bill_item)); node->customer_name = malloc(31 * sizeof(char)); // 分配客户名字内存 int i=0,choice; printf("\nMenu"); printf("\n-----------------"); for (i=0;i<5;i++){ printf("\n%d %s : %.2f",i+1,array[i].item_name,array[i].cost); } printf("\nEnter choice: "); scanf("%d",&choice); node->order_item_no = choice; while((getchar()) != '\n'); // 清除缓冲区换行 printf("\nEnter quantity: "); scanf("%d",&node->quantity); while((getchar()) != '\n'); // 清除缓冲区换行 node->next = NULL; count++; node->bill_no = count; node->total = array[choice-1].cost*node->quantity; printf("\nEnter customer name: "); fgets(node->customer_name,30,stdin); // 去掉fgets读取的换行符 size_t len = strlen(node->customer_name); if(len > 0 && node->customer_name[len-1] == '\n'){ node->customer_name[len-1] = '\0'; } printf("\nPurchase amount: %.2f \nNeed fast delivery(Extra 100rs will be charged)(y/n)?",node->total); c = getchar(); while((getchar()) != '\n'); // 清除缓冲区换行 if(c=='Y' || c=='y'){ node->total +=100; printf("\nFast delivery applied\nTotal %.2f",node->total); insert_at_start(node); } else{ printf("\nTotal: %.2f",node->total); insert_at_end(node); } } void display_list(){ printf("\nBill No\t\tOrder Item\t\tCname\t\tQ\t\tTotal"); struct bill_item* ptr = head->next; while(ptr!=NULL){ printf("\n%d\t\t%d\t\t%s\t\t%d\t\t%.2f",ptr->bill_no,ptr->order_item_no,ptr->customer_name,ptr->quantity,ptr->total); ptr = ptr->next; } }
内容的提问来源于stack exchange,提问作者AJITH RT
相关产品推荐
相关产品推荐

