初音未来の消失

商品管理系统

大一上C语言期末作业
动态链表真的好烦啊

这次主要纠正了自己的一个错误思想
一个链表的链表头是一个指针,而不是一个结点
所以,每次操作一个链表的时候,要传入指针的指针
才能达到修改第一个结点的目的

GoodList *Head; //这是指向链表头的指针
Change(&Head); //传入指针的指针

实验报告

#include 
#include 
#include 
#include 
#include 

#define MAX 100//最大商品数量 
int CurrentCnt = 0;//当前商品数量 

#define MAX_ID_LEN 30
#define MAX_NAME_LEN 30
#define MAX_PRICE_LEN 30
#define MAX_DISCOUNT_LEN 30
typedef struct{//商品信息结构 
    char    good_id[MAX_ID_LEN];
    char    good_name[MAX_NAME_LEN];
    int     good_price;
    char    good_discount[MAX_DISCOUNT_LEN];
    int     good_amount;
    int     good_remain;
}GoodInfo;

typedef struct node{//商品链表结点 
    GoodInfo data;
    struct node *next;
}GoodList;

FILE *fp;//文件指针用来操作文件 
int file_read(){
    fp = fopen("goodinfo.txt", "r");//读取文件 
    return fp != NULL;
}

void file_write(){
    fp= fopen("goodinfo.txt", "w");//写文件 
}

void file_close(){
    fclose(fp); 
}

void pause(){
    system("pause");
    system("cls");
}

bool check_nullfile(){//检查商品文件是否存在或者是否为空
    if(file_read()) return 0;//找到文件 
    else{
        file_write(); file_close();
        file_read();
        return 1;//没有找到文件 
    }
}

//--------------------------------------------------------------------
//查找一条商品记录
//--------------------------------------------------------------------
GoodList* good_find(GoodList *L,char *p){
    while(L)
        if(strcmp(L->data.good_id, p) == 0) return L;
        else L = L->next;
    return NULL;//没找到 
}

void info_change(GoodList *L) {
    printf("请输入新的商品信息:\n");
    printf("商品ID:"); scanf("%s",L->data.good_id);
    printf("商品名称:"); scanf("%s",L->data.good_name);
    printf("商品价格:"); scanf("%d",&(L->data.good_price));
    printf("商品折扣:"); scanf("%s",L->data.good_discount);
    printf("商品数量:"); scanf("%d",&(L->data.good_amount));
    printf("商品剩余:"); scanf("%d",&(L->data.good_remain));
    return;
}

void info_change_NoRepeat(GoodList *p,GoodList *L) {//p为新增的指针 , L为链表的头指针 
    printf("请输入新的商品信息:\n");
    printf("商品ID:"); scanf("%s",p->data.good_id);
    while(good_find(L,p->data.good_id) != NULL){
        printf("商品ID已存在,请重新输入:\n");
        printf("商品ID:"); scanf("%s",p->data.good_id);
    }

    printf("商品名称:"); scanf("%s",p->data.good_name);
    printf("商品价格:"); scanf("%d",&(p->data.good_price));
    printf("商品折扣:"); scanf("%s",p->data.good_discount);
    printf("商品数量:"); scanf("%d",&(p->data.good_amount));
    printf("商品剩余:"); scanf("%d",&(p->data.good_remain));
    return;
}


void Goodprint(GoodList *p){//打印单个商品链表节点的信息 
    printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
    printf("ID:%s\t名称:%s\t价格:%d\t折扣:%s\t数量:%d\t剩余:%d\n",p->data.good_id,p->data.good_name,p->data.good_price,p->data.good_discount,p->data.good_amount,p->data.good_remain);
    printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
}

void info_init(GoodList **L){//读取商品文件goodinfo.txt的内容,并建立链表L
    *L = NULL;
    CurrentCnt=0;

    if(check_nullfile())//检查是否为空 
        printf("商品文件不存在,已新建\n");
    else{
        GoodList *p, *now;
        while (!feof(fp)){//一直循环直到把文件读完
            p = (GoodList*) malloc(sizeof(GoodList));
            if(*L == NULL){//如果p是第一个非空节点 
                *L = p;
                now = p;//暂存之前的节点 
            }else{ 
                now -> next = p;
                now = p;
            }

            fscanf(fp, "%s", p->data.good_id);
            fscanf(fp, "%s", p->data.good_name);
            fscanf(fp, "%d", &(p->data.good_price));
            fscanf(fp, "%s", p->data.good_discount);
            fscanf(fp, "%d", &(p->data.good_amount));
            fscanf(fp, "%d", &(p->data.good_remain));
            CurrentCnt++;
        }
        now->next = NULL;//把尾节点中的指针置0 
    }
    file_close();
}

void DelAll(GoodList **L){//删除商品文件以及商品链表中的所有信息
    char str[MAX_ID_LEN];
    printf("将会清除所有文件及链表,确定吗?(Y/N):");
    scanf("%s",str);
    if(strcmp(str, "Y") != 0 && strcmp(str, "y") != 0){
        printf("操作已取消\n\n");
        return; 
    }
    printf("再次询问,这将造成数据的丢失,确定吗?(Y/N):");
    scanf("%s",str);
    if(strcmp(str, "Y") != 0 && strcmp(str, "y") != 0){
        printf("操作已取消\n\n");
        return; 
    }


    GoodList *p = *L, *now;
    while(p != NULL){//free指针 
        now = p->next;
        free(p);
        p = now;
    }

    remove("goodinfo.txt");//重写文件
    printf("成功删除所有数据\n\n");
    info_init(L);
}



//--------------------------------------------------------------------
//将当前商品链表中的内容存入商品文件goodinfo.txt,存盘后销毁链表L
//--------------------------------------------------------------------
void info_flush(GoodList **L){
    file_write();
    GoodList *p = *L, *now;
    while(p != NULL){//free指针
        fprintf(fp, "%s\t%s\t%d\t%s\t%d\t%d",p->data.good_id,p->data.good_name,p->data.good_price,p->data.good_discount,p->data.good_amount,p->data.good_remain);
        now = p->next;
        if(now != NULL)
            fprintf(fp, "\n");
        free(p);
        p = now;
    }

}

//--------------------------------------------------------------------
//在屏幕上输出所有商品信息
//--------------------------------------------------------------------
void OutputAll(GoodList *L){
    while(L){
        Goodprint(L);
        L = L -> next;
    }
}

void info_insert(GoodList **L) {
    GoodList *p = (GoodList*) malloc(sizeof(GoodList));
    GoodList *now = *L;

    int CHOICE;
    printf("请选择插入方法:\n");
    printf("\t1.头插法:\n");
    printf("\t2.尾插法:\n");
    printf("\t3.中间插入:\n\n");
    printf("输入您的选择:"); 

    scanf("%d",&CHOICE);
    switch(CHOICE){
        case 1:{//头插法 
            info_change_NoRepeat(p, *L);
            p->next = *L;
            *L = p;
            CurrentCnt++;
            break;
        }

        case 2:{//尾插法 
            info_change_NoRepeat(p, *L);
            if(*L == NULL) *L=p;
            else{
                while(now->next != NULL) now = now->next;
                now->next = p;
                p->next = NULL;//尾插法 
            }
            CurrentCnt++;
            break;
        }

        case 3:{
            char ID[MAX_ID_LEN];
            info_change_NoRepeat(p, *L);
            printf("请输入要将该信息插入到哪个ID后面:");
            scanf("%s",ID);

            GoodList *now;
            now=good_find(*L, ID);
            while(now == NULL){
                printf("没有找到该ID,请重新输入ID:");
                scanf("%s",ID);
                now=good_find(*L, ID);
            }
            p->next = now->next;
            now->next = p;

            CurrentCnt++;
            break;
        }



    } 
    return;
}

//--------------------------------------------------------------------
//删除一条商品记录
//--------------------------------------------------------------------
void info_dele(GoodList **L) {
    char ID[MAX_ID_LEN];
    GoodList *p;
    printf("请输入要删除的商品ID:");
    scanf("%s",ID);
    p = good_find(*L, ID);
    while(p == NULL){
        printf("未找到该商品,请重新输入ID:");
        scanf("%s",ID);
        p = good_find(*L, ID);
    }

    printf("\n你确定要删除该商品吗(默认否)?(Y/N):");
    scanf("%s",ID);//读入选项 
    if(strcmp(ID, "Y") == 0||strcmp(ID, "y") == 0){
        if(*L == p){
            *L = p->next;
            free(p);
        }else{
            GoodList* now = *L;//寻找p商品之前的那个结点 
            while(now->next != p) now = now->next;
            now->next = p->next;
            free(p);
        }
        CurrentCnt--;
        printf("已删除\n\n");
    }else printf("已取消\n\n");
    return;
}


void menu_print(){
    printf("商品的链表文件已建立,有%d个商品记录\n", CurrentCnt);
    printf("****************************************\n");
    printf("1.显示所有商品的信息:\n");
    printf("2.修改某个商品的信息:\n");
    printf("3.插入某个商品的信息:\n");
    printf("4.删除某个商品的信息:\n");
    printf("5.查找某个商品的信息:\n");
    printf("6.商品存盘并退出系统:\n");
    printf("7.对商品价格进行排序:\n");
    printf("8.(慎用)删除所有内容:\n");
    printf("其他,不存盘并退出系统:\n");
    printf("****************************************\n");
    printf("输入您的选择:");
}

void good_swap(GoodList* a,GoodList* b){//交换两个商品的位置 
    GoodList a_ = *a, b_ = *b;
    *a = b_;
    *b = a_;
    a->next = a_.next;
    b->next = b_.next;
    return;
}

void bubble_sort(GoodList **L){
    printf("正在冒泡排序...\n");
    for(int i=1;i<=CurrentCnt-1;i++){
        GoodList* now = *L;
        while(now->next != NULL){
            if(now->data.good_price > now->next->data.good_price)
                good_swap(now, now->next);
            now = now->next;
        }

    }
    printf("排序完成!\n");
    OutputAll(*L);
}


int main(){
    char str[MAX_ID_LEN];
    int CHOICE;
    GoodList *Head,*p;
    Head=NULL;

    info_init(&Head);//读取文件

    do{
        printf("超市商品管理系统\n");
        CHOICE=0;
        menu_print();//菜单 

        scanf("%d",&CHOICE);//输入选择 
        switch(CHOICE){
            case 1:{
                OutputAll(Head);
                pause();
                break;
            }

            case 2:{
                int ok=0;
                do{
                    printf("请输入需要修改的商品ID(输入-1退出):"); 
                    scanf("%s",str);
                    if(strcmp(str,"-1") == 0) break;
                    p = good_find(Head, str);
                    if(p == NULL) printf("\n对不起,没有找到该商品,请重新输入:\n");
                    else Goodprint(p),ok=1;
                }while(!p);

                if(ok){
                    info_change(p);
                    printf("\n修改成功!\n\n");
                }
                pause();
                break;
            }

            case 3:{
                info_insert(&Head);
                pause();
                break;
            }

            case 4:{
                info_dele(&Head);
                pause();
                break;
            }

            case 5:{
                printf("请输入需要查询的商品ID:"); 
                scanf("%s",str);
                p = good_find(Head, str);
                if(p == NULL) printf("\n对不起,没有找到该商品\n\n");
                else Goodprint(p);

                pause();
                break;
            }


            case 6:{
                char str[MAX_ID_LEN];
                printf("确定要保存吗?(Y/N):");
                scanf("%s",str);

                if(strcmp(str, "Y") == 0||strcmp(str, "y") == 0){
                    info_flush(&Head);
                    printf("保存成功,即将退出系统\n");
                    CHOICE=0;//退出信号 
                }else{
                    printf("已取消\n");
                    pause();
                }
                break;
            }

            case 7:{
                bubble_sort(&Head);

                pause();
                break;
            }

            case 8:{
                DelAll(&Head);

                pause();
                break;
            }

            default:{
                CHOICE=0;//退出信号 
                printf("\n即将不存盘并退出系统\n\n\n\n");
            }
        }
    }while(CHOICE);

    system("pause");
    return 0;
}

退出移动版