写程序出了问题,问了好多人都没解决,因为他们都不用头插法,我才学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;
}
}