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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:05:27