ORIGIN-JOKER 2023-02-25 16:10 采纳率: 88.9%
浏览 19
已结题

编号唯一性&读取文件出错,如何解决?

写程序出了问题,问了好多人都没解决,因为他们都不用头插法,我才学C不久,好多知识都不知道,数据结构都没学,我希望有巨佬能忙里偷闲帮我看下我的问题,我必感激不尽
1、校验编号唯一性
很多人用录入信息用的是循环的写法,我没用,于是我就不会校验了,我问了别人,给我说是能用递归写,TA帮我写了一点,我根据我自己的完善,然后程序就跑不起来了,我调试了好多次都没解决。我的希望是,传入pjd->lj.bh,用一个函数能够判断链表里有无相同的编号,有就重新输入,没有就继续录入信息,希望有巨佬帮帮忙,告诉我为什么,或者带我一下,写一个检验的函数直接发给我,我的环境是dev的,囚囚了
2、打开文件
如果我把之前存在文件里东西用记事本打开并删除,然后我重新保存信息,程序可以执行,但是当我再次保存信息后选择打开文件,程序就直接结束了,并且文件一直只有1kb,我不知道为什么,明明我每次寸的时候都要开辟1kb的空间的,我也调试过,不过以我的水平我真的看不出来是为什么,我同学写的从文件调用可以是先在里面填所有信息,但是我的存信息村的是二进制,用记事本打开也是类似的东西,我不知道是为什么。可以的话,希望你们可以改我的代码,打开函数,文件的代码改成你们的文件,再测试一下,或者直接写一段新的发给我让我观摩观摩,
以下是我的代码(改),这是我改过的代码,源代码就是把校验模块删除了,最下面是我的文件保存和读取函数还有校验唯一性的函数

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>

//定义采购信息 
typedef struct _car
{
    char bh[20]; //编号
    char mc[10]; //名称
    int year; //日期
    int month;
    int day;
    char cgy[20];//采购员
    int num;     //数量
    double dj;    //单价
    char dw[5];  //单位 
}car;


//结点 
typedef struct _jd
{
    car lj;      //零件

    struct _jd* pnext;//指向下一个结点的指针 
}jd;

//头结点
jd* g_pHead = NULL;

//函数:菜单 
void menu();

//函数:录入信息
void lr();

//函数:打印信息
void dy();

//函数:通过编号查找零部件
jd* cz_bh();

//函数:通过名称查找零部件
jd* cz_mc();

//函数:修改零部件信息
void xg();

//函数:删除零部件是头结点的信息
void t_sc();

//函数:删除零部件不是头结点的信息
void ft_sc();

//函数:统计采购金额 
double  cgje();

//函数:文件的保存
void wj_bc();

//函数:文件的读取
void wj_dq();

//函数:释放内存 
void sf_nc();

//验证唯一性
void check(char _bh[20]); 

int main()
{
    while (1)
    {
        jd* p;
        p = g_pHead;

        system("cls"); //清屏 

        //打开菜单 
        menu();

        //输入选择 
        printf("请输入你的选择(直接点击数字,不用进行回车)\n");

        //从键盘中接收一个字符来直接操作 
        char ch = getch();
        switch (ch)
        {
        case '1':
            printf("接下来是采购信息的录入\n");
            lr();
            break;

        case '2':
            printf("接下来是打印所有零部件采购信息\n");
            dy();
            break;

        case '3':
        {
            printf("接下来是通过编号查找零部件\n");
            p = cz_bh();
            if (p != NULL)
            {
                printf("*编号:%s\t*名称:%s\t*日期:%d-%d-%d\t*采购员:%s\t*数量%d\t*单价:%.2lf\t*单位:%s*\n", p->lj.bh, p->lj.mc, p->lj.year, p->lj.month, p->lj.day, p->lj.cgy, p->lj.num, p->lj.dj, p->lj.dw);
            }

            else
            {
                printf("查找失败,未检查到所输入的编号,请您重新检查输入\n");
            }
            system("pause");
            break;
        }

        case '4':
        {
            printf("接下来是通过名称查找零部件\n");
            p = cz_mc();
            if (p != NULL)
            {
                printf("*编号:%s\t*名称:%s\t*日期:%d-%d-%d\t*采购员:%s\t*数量%d\t*单价:%.2lf\t*单位:%s*\n", p->lj.bh, p->lj.mc, p->lj.year, p->lj.month, p->lj.day, p->lj.cgy, p->lj.num, p->lj.dj, p->lj.dw);
            }

            else if (p == NULL)
            {
                printf("查找失败,未检查到所输入的名称,请您重新检查输入\n");
            }
            system("pause");
            break;
        }

        case '5':
            printf("接下来是给定采购编号,修改采购信息\n");
            xg();
            break;

        case '6':
        {
            int i;
            printf("接下来是给定采购编号,删除采购信息\n");
            printf("请输入需要删除的零部件的编号是否是您最后输入的零部件(是或只有一个零部件按1,不是按0):\n");
            scanf("%d", &i);
            if (i == 1)
            {
                t_sc();
            }
            else if (i == 0)
            {
                ft_sc();
            }
            else
            {
                printf("对不起,您的输入有误,请重新检查输入\n");
                system("pause");
            }
            break;
        }

        case '7':
        {
            double sum;
            sum = cgje();
            printf("总金额为=%.2lf\n", sum);
            system("pause");
            break;
        }
        
        case '8':
        {
            wj_bc();
            break;        
        }
        
        case '9':
        {
           wj_dq();
           break;         
        }
        
        case 'a':
        {
            sf_nc();
            break;
        }
            

        case'0':
            printf("感谢您的下次使用,再见");
            return 0;
            break;

        default:
            printf("您当前输入有误,请您确认您的操作再重试\n");
            system("pause");
            break;
        }
    }

    return 0;
}

void menu()
{
    printf("\t******汽车零部件采购程序******\n");
    printf("\t(1)能从键盘输入采购信息。");
    printf("\n\t(2)打印所有零部件信息。");
    printf("\n\t(3)指定采购编号,显示采购的零部件信息。");
    printf("\n\t(4)指定零部件名称,显示该零部件的所有采购信息。");
    printf("\n\t(5)给定采购编号,修改采购信息。");
    printf("\n\t(6)给定采购编号,删除采购信息。");
    printf("\n\t(7)给定名称,采购员或日期来统计采购金额。");
    printf("\n\t(8)把数据保存在文件中。");
    printf("\n\t(9)把数据从文件中调出。");
    printf("\n\t(a)释放内存"); 
    printf("\n\t(0)退出程序\n");
}

void lr()
{
    //创建一个新结点
    jd* pjd = (jd*)malloc(sizeof(jd));
    pjd->pnext = NULL;

    

    printf("请输入编号(例如:1 2 3):\n\t");
    scanf("%s", pjd->lj.bh); //编号
    //check(pjd->lj.bh);

    printf("请输入零部件名称(例如:xxx):\n\t");
    scanf("%s", pjd->lj.mc); //名称

    printf("请输入年份(例如:2010):\n\t");
    scanf("%d", &pjd->lj.year); //日期
    if (pjd->lj.year < 1900 || pjd->lj.year >2023)
    {
        printf("年份输入错误,正确年份为1900-2023,请重新输入:\n");
        scanf("%d", &pjd->lj.year);
    }

    printf("请输入月份(例如:10):\n\t");
    scanf("%d", &pjd->lj.month);
    if (pjd->lj.month < 1 || pjd->lj.month>12)
    {
        printf("月份输入错误,正确月份为1-12,请重新输入:\n\t");
        scanf("%d", &pjd->lj.month);
    }

    printf("请输入天份(例如:22):\n\t");
    scanf("%d", &pjd->lj.day);
    if ((pjd->lj.year % 4 == 0 && pjd->lj.year % 100 != 0) || pjd->lj.year % 400 == 0)
    {
        if (pjd->lj.month == 1 || pjd->lj.month == 3 || pjd->lj.month == 5 || pjd->lj.month == 7 || pjd->lj.month == 8 || pjd->lj.month == 10 || pjd->lj.month == 12)
        {
            if (pjd->lj.day < 1 || pjd->lj.day>31)
            {
                printf("亲,1,3,5,7,8,10,12月仅有31天哦,请重新输入:\n\t");
                scanf("%d", &pjd->lj.day);
            }
        }

        else if (pjd->lj.month == 4 || pjd->lj.month == 6 || pjd->lj.month == 9 || pjd->lj.month == 11)
        {
            if (pjd->lj.day < 1 || pjd->lj.day>30)
            {
                printf("亲,4,6,9,11月仅有30天哦,请重新输入:\n\t");
                scanf("%d", &pjd->lj.day);
            }
        }

        else if (pjd->lj.month == 2)
        {
            if (pjd->lj.day < 1 || pjd->lj.day>29)
            {
                printf("亲,虽然是闰年,但是2月也仅有29天哦,请重新输入:\n\t");
                scanf("%d", &pjd->lj.day);
            }
        }
    }

    else
    {
        if (pjd->lj.month == 1 || pjd->lj.month == 3 || pjd->lj.month == 5 || pjd->lj.month == 7 || pjd->lj.month == 8 || pjd->lj.month == 10 || pjd->lj.month == 12)
        {
            if (pjd->lj.day < 1 || pjd->lj.day>31)
            {
                printf("亲,1,3,5,7,8,10,12月仅有31天哦,请重新输入:\n\t");
                scanf("%d", &pjd->lj.day);
            }
        }

        else if (pjd->lj.month == 4 || pjd->lj.month == 6 || pjd->lj.month == 9 || pjd->lj.month == 11)
        {
            if (pjd->lj.day < 1 || pjd->lj.day>30)
            {
                printf("亲,4,6,9,11月仅有30天哦,请重新输入:\n\t");
                scanf("%d", &pjd->lj.day);
            }
        }

        else if (pjd->lj.month == 2)
        {
            if (pjd->lj.day < 1 || pjd->lj.day>28)
            {
                printf("亲,虽然是平年年,但是2月也仅有28天哦,请重新输入:\n\t");
                scanf("%d", &pjd->lj.day);
            }
        }
    }


    printf("请输入采购员名称(例如:张三):\n\t");
    scanf("%s", pjd->lj.cgy);//采购员 

    printf("请输入采购数量(例如:2):\n\t");
    scanf("%d", &pjd->lj.num);//数量 

    printf("请输入零部件单价(例如:2.00):\n\t");
    scanf("%lf", &pjd->lj.dj);//单价 

    printf("请输入零部件价格单位(例如:SF):\n\t");
    scanf("%s", pjd->lj.dw); //单位 
    
    //头插法
    if (g_pHead == NULL) //没有结点,赋予结点 
    {
        g_pHead = pjd;
    }
    else                //有结点
    {
        pjd->pnext = g_pHead;//新结点的下一个为头结点
        g_pHead = pjd;      //则头结点为新设的结点 
    }

    printf("零部件信息录入成功!\n");
    printf("如果您想继续输入,请在看到请按任意键继续后回到菜单继续按1录入信息\n");

    system("pause"); //停顿 
    return;
}
//*********************
//********
//*************

void dy()
{
    printf("**************************************************************\n");
    printf("*\t               欢迎使用汽车零部件管理系统            *\n");
    printf("**************************************************************\n");

    printf("*编号\t*名称\t*日期\t        *采购员\t*数量\t*单价\t*单位*\n");
    printf("**************************************************************\n");

    //遍历链表
    jd* p = g_pHead; //让p指向头指针
    while (p != NULL)//只要结点不为空就让循环往下走 
    {
        printf("*%s\t*%s\t*%d-%d-%d\t*%s\t*%d\t*%.2lf\t*%s*\n",
            p->lj.bh,
            p->lj.mc,
            p->lj.year,
            p->lj.month,
            p->lj.day,
            p->lj.cgy,
            p->lj.num,
            p->lj.dj,
            p->lj.dw);

        p = p->pnext; //指向下一个 
    }

    system("pause");
}

jd* cz_bh()
{
    char cz_bh[20];

    printf("请输入你想查找的零件的编号:\n");
    scanf("%s", cz_bh);

    jd* p = g_pHead;
    while (p != NULL)
    {
        if (strcmp(p->lj.bh, cz_bh) == 0) //会报警告 
        {
            return p;
        }

        p = p->pnext;
    }
    return NULL;
}

jd* cz_mc()
{
    char cz_mc[20];

    printf("请输入你想查找的零件的名称:\n");
    scanf("%s", cz_mc);

    jd* p = g_pHead;
    while (p != NULL)
    {
        if (strcmp(p->lj.mc, cz_mc) == 0)
        {
            return p;
        }

        p = p->pnext;
    }
    return NULL;
}

void xg()
{
    int i = 0;

    char xg_bh[20];

    printf("请输入需要修改的零部件的采购编号\n");
    scanf("%s", xg_bh);

    jd* p = g_pHead;
    while (p != NULL)
    {
        if (strcmp(p->lj.bh, xg_bh) == 0) //p->li.bh与xg_bh不能用等号比较 
        {
            printf("请输入您想修改的零件信息:\n修改编号请按1\n修改名称请按2\n修改日期请按3\n修改采购员请按4\n修改数量请按5\n修改单价请按6\n修改单位请按7\n如果要全部修改请按0\n");
            scanf("%d", &i);

            if (i == 1)
            {
                printf("您好,请输入修改后的编号:\n");
                scanf("%s", p->lj.bh);
            }

            else if (i == 2)
            {
                printf("您好,请输入修改后的名称:\n");
                scanf("%s", p->lj.mc);
            }

            else if (i == 3)
            {
                printf("您好,如果您想修改年份请按1,修改月份请按2,修改天份请按3:\n");
                scanf("%d", &i);

                if (i == 1)
                {
                    printf("请输入修改后的年份:\n\t");
                    scanf("%d", &p->lj.year);
                }

                else if (i == 2)
                {
                    printf("请输入修改后的月份:\n\t");
                    scanf("%d", &p->lj.month);
                }

                else if (i == 3)
                {
                    printf("请输入修改后的天份:\n\t");
                    scanf("%d", &p->lj.day);
                }
            }

            else if (i == 4)
            {
                printf("您好,请输入修改后的采购员:\n");
                scanf("%s", p->lj.cgy);
            }

            else if (i == 5)
            {
                printf("您好,请输入修改后的数量:\n");
                scanf("%d", &p->lj.num);
            }

            else if (i == 6)
            {
                printf("您好,请输入修改后的单价:\n");
                scanf("%lf", &p->lj.dj);
            }

            else if (i == 7)
            {
                printf("您好,请输入修改后的单位:\n");
                scanf("%s", p->lj.dw);
            }

            else if (i == 0)
            {
                printf("您好,请输入修改后的编号 名称 日期 采购员 数量 单价 单位:\n");
                scanf("%s %s %d %d %d %s %d %lf %s", p->lj.bh, p->lj.mc,&p->lj.year,&p->lj.month,&p->lj.day, p->lj.cgy, &p->lj.num, &p->lj.dj, p->lj.dw);
            }

            else
            {
                printf("对不起输入错误,请检查您的输入再重试");
                system("pause");
                break;
            }

            printf("修改成功\n");
            system("pause");
            break;
        }
        p = p->pnext;
    }

    if (p == NULL)
    {
        printf("未能找到此采购编号对应零部件,请检查编号\n");
        system("pause");
    }
}

void t_sc()
{
    jd* p1;
    char sc_bh[20];
    printf("请输入你所想要删除的零部件的编号:");
    scanf("%s", sc_bh);

    //如果是头结点 
    if (strcmp(g_pHead->lj.bh, sc_bh) == 0)
    {
        p1 = g_pHead;            //备份头结点 
        g_pHead = g_pHead->pnext;// 将头结点指向下一个结点 
        free(p1); //删除就是释放这段内存 ,p1被赋予了头结点,但是头结点已经指向下一个结点 
        printf("恭喜,删除成功\n");
        system("pause");
        return;
    }

    else
    {
        printf("对不起,删除失败,请检查你输入的编号\n");
        system("pause");
        return;
    }
}

void ft_sc()
{
    //如果不是头结点
    char sc1_bh[20];
    printf("请输入你所想要删除的零部件的编号:");
    scanf("%s", sc1_bh);
    jd* p = g_pHead;
    jd* p2;                  //p2是备份的 
    while (p2->pnext != NULL)
    {
        if (strcmp(p->pnext->lj.bh, sc1_bh) == 0)
        {
            p2 = p->pnext;             //备份头结点 
            p->pnext = p->pnext->pnext;//中间结点(要删除的结点)的上一个结点是头结点,头结点的下一个结点是中间节点的后一个结点 ,把中间结点指向第三个结点 
            free(p2);
        }

        if (p->pnext == NULL) //中间结点已删除.  NULL会警告,'0'不会 ,char变量和指针变量不能比较 
        {
            printf("恭喜,成功删除\n");
            system("pause");
            return;
        }

        p = p->pnext;

        if (p->pnext == NULL)//跳出循环,表示零件不存在
        {
            printf("对不起,删除失败,请检查你输入的编号\n");
            system("pause");
            return;
        }
    }

}

double  cgje()
{
    int i = 0,j = 0;
    double sum = 0;
    char tj_mc[20];
    char tj_cgy[20];
    int tj_rq_year;
    int tj_rq_month;
    int tj_rq_day;

    jd* p = g_pHead;

    printf("您想依据什么来统计采购金额(依据名称请按1,依据采购员请按2,依据采购日期请按3)\n");
    scanf("%d", &i);

    if (i == 1)
    {
        printf("请输入被统计零件的名称:\n");
        scanf("%s", tj_mc);

        while (p != NULL)
        {
            if (strcmp(tj_mc, p->lj.mc) == 0)
            {
                sum += p->lj.dj * p->lj.num;
                p = p->pnext;
            }

            else if (strcmp(tj_mc, p->lj.mc) != 0)
            {
                printf("您输入的名称有误,请返回菜单后再重新统计\n");
                return 0;
            }
        }
        return sum;
    }

    else if (i == 2)
    {
        printf("请输入被统计零件的采购员:\n");
        scanf("%s", tj_mc);

        while (p != NULL)
        {
            if (strcmp(tj_cgy, p->lj.cgy) == 0)
            {
                sum += p->lj.dj * p->lj.num;
                p = p->pnext;
            }

            else if (strcmp(tj_cgy, p->lj.cgy) != 0)
            {
                printf("您输入的采购员有误,请返回菜单后再重新统计\n");
                return 0;
            }
        }
        return sum;
    }
    
    else if(i==3)
    {
        printf("按年统计请按1,按月份统计请按2,按天份统计请按3\n");
        scanf("%d",&j);
        
        if(j==1)
        {
            printf("您想查找那一年的总金额(例如:2022):\n");
            scanf("%d",&tj_rq_year);
            while(p != NULL)
            {
                if(tj_rq_year==p->lj.year)
                {
                    sum += p->lj.dj * p->lj.num;
                    p=p->pnext;
                }
            }
            return sum;
        }
        
        else if(j==2)
        {
            printf("您想查找那一月的总金额(例如:2022):\n");
            scanf("%d",&tj_rq_month);
            while(p != NULL)
            {
                if(tj_rq_month==p->lj.month)
                {
                    sum += p->lj.dj * p->lj.num;
                    p=p->pnext;
                }
            }
            return sum;
        }
        
        else if(j==3)
        {
            printf("您想查找那一天的总金额(例如:2022):\n");
            scanf("%d",&tj_rq_day);
            while(p != NULL)
            {
                if(tj_rq_day==p->lj.day)
                {
                    sum += p->lj.dj * p->lj.num;
                    p=p->pnext;
                }
            }
            return sum;
        }
    }
}

void wj_bc()
{
    //打开文件
    FILE* fp = fopen("C:\\Users\\joker\\dy.data","w");
    
    if(fp == NULL)
    {
        printf("打开文件失败\n");
        return;
    }
    
    jd* njd = g_pHead;
    while(njd != NULL)
    {
        fwrite(&njd->lj,1,sizeof(car),fp); //结构体内容 几kb 以什么方式 
        njd = njd->pnext;
    }
    
    //关闭文件
    fclose(fp); 
    printf("数据保存成功\n");
    system("pause");
    system("cls");
    return;
}

void wj_dq()
{
    //打开文件
    FILE* fp = fopen("C:\\Users\\joker\\dy.data","r");
    if(fp == NULL)
    {
        printf("抱歉,文件内容为空\n");
        return;
    }
    
    //读文件
    car lj;
    while(fread(&lj,1,sizeof(car),fp)) //feof判断是否到末尾 ,但是会多一行 
    {
        //创建一个新结点
        jd* djd=(jd*)malloc(sizeof(car)); 
        djd->pnext=NULL;
        
        memcpy(djd,&lj,sizeof(lj)); //添加头文件<string.h> 
        
        //头插法
        if (g_pHead == NULL) //没有结点,赋予结点 
        {
            g_pHead = djd;
        }
        else                //有结点
        {
             djd->pnext = g_pHead;//新结点的下一个为头结点
            g_pHead = djd;      //则头结点为新设的结点 
        }
    } 
    
    //关闭文件
    fclose(fp); 
    printf("加载数据成功!\n");
    system("pause");
}

void sf_nc()
{
    jd* sf_jd =(jd*)malloc(sizeof(jd));
    sf_jd->pnext=NULL;
    //头插法
        if (g_pHead == NULL) //没有结点,赋予结点 
        {
            g_pHead = sf_jd;
        }
        else                //有结点
        {
             sf_jd->pnext = g_pHead;//新结点的下一个为头结点
            g_pHead = sf_jd;      //则头结点为新设的结点 
        }
        
        while(sf_jd!=NULL)
        {
            sf_jd=sf_jd->pnext;
            free(sf_jd);
        }
}

void check(char _bh[20])
{
    jd* p = g_pHead;
    while(p->pnext!=0)
    {
        if(strcmp(p->lj.bh,_bh)==0)
        {
            printf("编号重复,请重试\n");
            scanf("%s",p->lj.bh);
            check(_bh);
        }
        p=p->pnext;
    }
}

  • 写回答

1条回答 默认 最新

  • MarkHan_ 2023-02-25 16:26
    关注

    该回答引用GPTᴼᴾᴱᴺᴬᴵ
    1.校验编号唯一性
    可以遍历链表,逐个比较编号是否相同,如果有相同的就返回1,没有相同的就返回0。下面是一个示例代码:

    int checkNumberUnique(char* number, Node* head) {
        Node* p = head;
        while (p != NULL) {
            if (strcmp(number, p->lj.bh) == 0) {
                return 1; // 编号已存在
            }
            p = p->next;
        }
        return 0; // 编号不存在
    }
    
    
    

    在录入信息时,可以使用这个函数来校验编号的唯一性。如果返回1,则需要重新输入编号;如果返回0,则可以继续录入信息。

    2.打开文件
    可能是因为你每次都是开辟1KB的空间,但是实际上你保存的信息并不一定占用了整个1KB的空间。因此,读取文件时需要知道实际保存的信息长度,而不能简单地使用1KB的长度。

    下面是一个示例代码,用于读取文件中保存的信息:

    void readFile(char* filename, Node** head) {
        FILE* fp;
        fp = fopen(filename, "rb");
        if (fp == NULL) {
            printf("File not found.\n");
            return;
        }
        while (!feof(fp)) {
            Node* newNode = (Node*)malloc(sizeof(Node));
            int bytesRead = fread(&(newNode->lj), sizeof(Info), 1, fp);
            if (bytesRead != 1) {
                free(newNode);
                break;
            }
            newNode->next = NULL;
            addNode(head, newNode);
        }
        fclose(fp);
    }
    
    
    

    注意,在使用fread()函数读取文件时,需要判断是否读到了文件的末尾(feof()函数),否则会导致读取错误。同时,每次读取一个结构体的大小,而不是固定的1KB。

    希望这些代码可以帮助你解决问题。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 3月9日
  • 已采纳回答 3月1日
  • 创建了问题 2月25日

悬赏问题

  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改