#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
typedef struct hapen
{
int year; //年
int month; //月
int num; //数量
}dat;
typedef struct project //物品基础信息
{
char name[50]; //物品名称
int price; //物品价格
}pro;
typedef union ddoing //进、出货性质数据
{
dat in; //进货数据
dat out; //售货数据
}ndata;
typedef struct dddoing //进出货数据
{
char kind; //“i”为进货;“o”为售货
pro prodata; //物品信息
ndata rdata; //进\出货性质数据
}justdo;
typedef union kinds //基础信息或流动数据信息共用体
{
pro data; //物品基础信息
justdo tdata; //流动数据
}choose;
typedef struct LNode
{
char kinds;// 选择基础信息或流动数据信息 “A”为基础信息,“C”为流动数据
choose doit;
struct LNode* next;
}LinkList;
char nam[50]; //物品名称
int pric; //物品价格
int yea; //年
int mont; //月
int nu; //数量
char kin; //进出货情况
char ki; //选择基础信息或流动数据信息 “A”为基础信息,“C”为流动数据
/*void InitList(LinkList* L) //初始化链表
{
L = (LinkList*)malloc(sizeof(LinkList));
L->next = NULL;
}
*/
void ListInsert(LinkList* L, LinkList* p)//插入新的节点
{
LinkList* q = NULL;
q = L;
p->next = q->next;
q->next = p;
}
void addproject(LinkList* L) //增加新物品信息
{
printf("请输入物品信息");
LinkList* q = L->next;
while (q != NULL)//移动到链表结尾
{
q = q->next;
}
if (q == NULL)
{
LinkList* p;
p = (LinkList*)malloc(sizeof(LinkList));
p->next = NULL;
printf("请选择你要添加的方式(“A”为基础信息,“B”为流动数据):\n");
scanf("%c", &ki);
if ('C' == ki) //进行流动数据操作
{
p->kinds, ki;
printf("请进货出货最频繁也限制在每个月只记录一次\n");
printf("物品名称(不可有空格):\n");
scanf("%s", nam);
strcpy(p->doit.tdata.prodata.name, nam);
printf("物品价格/元:\n");
scanf("%d", &pric);
p->doit.tdata.prodata.price = pric;
printf("信息情况(“i”为进货;“o”为售货):\n");
scanf("%c", kin);
p->doit.tdata.kind = kin;
if (kin == 'i') //进货操作
{
printf("输入进货年:\n");
scanf("%d", yea);
p->doit.tdata.rdata.in.year = yea;
printf("输入进货月:\n");
scanf("%d", mont);
p->doit.tdata.rdata.in.month = mont;
printf("输入进货数量:\n");
scanf("%d", nu);
p->doit.tdata.rdata.in.num = nu;
}
if (kin == 'o') //售货操作
{
printf("输入售货年:\n");
scanf("%d", yea);
p->doit.tdata.rdata.out.year = yea;
printf("输入售货月:\n");
scanf("%d", mont);
p->doit.tdata.rdata.out.month = mont;
printf("输入售货数量:\n");
scanf("%d", nu);
p->doit.tdata.rdata.out.num = nu;
}
else
{
printf("输入错误(“I”为进货;“O”为售货),请从头操作\n");
}
}
if ('A' == ki) //进行基础信息操作
{
p->kinds = ki;
printf("开始添加物品基础信息\n");
printf("物品名称(不可有空格):\n");
scanf("%s", nam);
strcpy(p->doit.data.name, nam);
printf("物品价格/元:\n");
scanf("%d", &pric);
p->doit.data.price = pric;
}
else
{
printf("输入错误(“A”为基础信息,“C”为流动数据),请从头操作\n");
}
ListInsert(L, p);
}
}
void deletedata(LinkList* L)//删除数据
{
if (L->next = NULL)
{
printf("还没有数据信息,请先增加物品数据信息\n");
return;
}
LinkList* p, * pre;
pre = L;
p = pre->next;
int judge = 0;
printf("请输入你想删除的数据类型( “A”为基础信息,“C”为流动数据):\n");
scanf("%c", &ki);
if (ki == 'A')
{
printf("请输入你想删除的物品名称:\n");
scanf("%s", nam);
while (p != NULL)
{
if (0 == strcmp(p->doit.data.name, nam))
{
judge = 1;
pre->next = p->next;
free(p);
printf("删除基本物品数据成功\n");
break;
}
pre = p;
if (p != NULL)
p = p->next;
}
if (judge == 0)
printf("这个物品信息不存在\n");
}
if (ki == 'C')
{
printf("请输入你想删除的信息情况(“i”为进货;“o”为售货):\n");
scanf("%c", &kin);
printf("请输入你想删除买卖情况数据的物品名称:\n");
scanf("%s", nam);
printf("请输入你想删除买卖物品的时间信息\n");
printf("年:\n");
scanf("%d", yea);
printf("月:\n");
scanf("%d", mont);
while (p != NULL)
{
if (kin == 'I')
{
if ((p->doit.tdata.kind = kin) && (0 == strcmp(p->doit.tdata.prodata.name, nam)) && (p->doit.tdata.rdata.in.year = yea) && (p->doit.tdata.rdata.in.month = mont))
{
judge = 1;
pre->next = p->next;
free(p);
printf("删除进货物品数据成功\n");
break;
}
pre = p;
p = p->next;
}
if (kin == 'O')
{
if ((p->doit.tdata.kind = kin) && (0 == strcmp(p->doit.tdata.prodata.name, nam)) && (p->doit.tdata.rdata.out.year = yea) && (p->doit.tdata.rdata.out.month = mont))
{
judge = 1;
pre->next = p->next;
free(p);
printf("删除售货物品数据成功\n");
break;
}
pre = p;
p = p->next;
}
else
{
printf("输入错误,请从头开始\n");
break;
}
}
if (judge == 0)
printf("这个信息不存在\n");
}
else
{
printf("输入错误,请从头开始\n");
}
}
int ListLength(LinkList* L)//求链表长度
{
int n = 0;
LinkList* p, * q;
p = L;
do
{
p = p->next;
printf("1");
n++;
} while (p!= NULL);
return n;
}
void finddata(LinkList* L) //按照名称查找并输出该物品信息
{
printf("请输入你要查询的物品名称:\n");
scanf("%s", nam);
LinkList* P;
P = L->next;
while (P != NULL)
{
if (('A' == P->kinds) && (0 == strcmp(P->doit.data.name, nam)))
{
printf("名称:%s\t价格%d元/个\n", P->doit.data.name, P->doit.data.price);
break;
}
P = P->next;
}
if (P == NULL)
printf("该物品不存在\n");
}
void displaypro(LinkList* L)//列出所有物品基础信息
{
LinkList* q = L->next;
if (q == NULL)
{
printf("还没有物品基础信息,请增加物品基础信息\n");
return;
}
while (q != NULL)
{
if (('A' == q->kinds) && (0 == strcmp(q->doit.data.name, nam)));
{
printf("名称:%s\t价格%d元/个\n", q->doit.data.name, q->doit.data.price);
}
q = q->next;
}
printf("列出结束\n");
}
void displayin(LinkList* L)//列出所有进货物品信息
{
LinkList* q = L->next;
if (q == NULL)
{
printf("还没有物品进货信息,请增加物品进货信息\n");
return;
}
while (q != NULL)
{
printf("有");
if (('C' == q->kinds) && ('i' == q->doit.tdata.kind))
{
printf("名称:%s\t价格%d元/个\t购进时间:%d年%d月\t购进个数:%d个\n", q->doit.tdata.prodata.name, q->doit.tdata.prodata.price, q->doit.tdata.rdata.in.year, q->doit.tdata.rdata.in.month, q->doit.tdata.rdata.in.num);
}
q = q->next;
}
}
void displayout(LinkList* L)//列出所有售货物品信息
{
LinkList* q = L->next;
if (q == NULL)
{
printf("还没有物品基础信息,请增加物品基础信息\n");
return;
}
while (q != NULL)
{
if (('C' == q->kinds) && ('o' == q->doit.tdata.kind))
{
printf("名称:%s\t价格%d元/个\t购进时间:%d年%d月\t购进个数:%d个\n", q->doit.tdata.prodata.name, q->doit.tdata.prodata.price, q->doit.tdata.rdata.out.year, q->doit.tdata.rdata.out.month, q->doit.tdata.rdata.out.num);
}
q = q->next;
}
}
void savedata(LinkList* L)//保存至文件夹
{
FILE* fp;
LinkList* p = L->next;
if ((fp = fopen("data.txt", "w")) == NULL)// 以可写的方式打开当前目录下的.txt
{
printf("不能打开此文件,请按任意键退出\n");
exit(1); //异常退出
}
while (p != NULL)
{
if ('A' == p->kinds)
{
fprintf(fp, "%c %s %d\n", p->kinds, p->doit.data.name, p->doit.data.price);
p = p->next;
printf("保存基本信息成功\n");
}
else if ('C' == p->kinds)
{
if ('i' == p->doit.tdata.kind)
{
fprintf(fp, "%c %c %s %d %d %d %d", p->kinds, p->doit.tdata.kind, p->doit.tdata.prodata.name, p->doit.tdata.prodata.price, p->doit.tdata.rdata.in.year, p->doit.tdata.rdata.in.month, p->doit.tdata.rdata.in.num);
p = p->next;
printf("保存进货信息成功\n");
}
if ('o' == p->doit.tdata.kind)
{
fprintf(fp, "%c %c %s %d %d %d %d", p->kinds, p->doit.tdata.kind, p->doit.tdata.prodata.name, p->doit.tdata.prodata.price, p->doit.tdata.rdata.out.year, p->doit.tdata.rdata.out.month, p->doit.tdata.rdata.out.num);
p = p->next;
printf("保存售货信息成功\n");
}
}
}
fclose(fp);
}
void readdata(LinkList* L)//读取文件中的信息拷贝到程序中
{
FILE* fp;
fp = fopen("data.txt", "r");//以只读方式打开文件夹
if (fp == NULL)
{
printf("文件不存在\n");
exit(0); //终止程序
}
while (!feof(fp))
{
LinkList* n = (LinkList*)malloc(sizeof(LinkList));
fscanf(fp, "%c", &ki);
if (ki == 'A')
{
fscanf(fp, "%s %d", nam, &pric);
n->kinds = ki;
strcpy(n->doit.data.name, nam);
n->doit.data.price = pric;
ListInsert(L, n);//插入新的节点
n = n->next;
}
if (ki == 'C')
{
fscanf(fp, "%c", &kin);
if (kin == 'i')
{
fscanf(fp, "%s %d %d %d %d", nam, &pric, &yea, &mont, &nu);
n->kinds = ki;
n->doit.tdata.kind = kin;
strcpy(n->doit.tdata.prodata.name, nam);
n->doit.tdata.prodata.price = pric;
n->doit.tdata.rdata.in.year = yea;
n->doit.tdata.rdata.in.month = mont;
n->doit.tdata.rdata.in.num = nu;
ListInsert(L, n);//插入新的节点
n = n->next;
}
if (kin == 'o')
{
fscanf(fp, "%s %d %d %d %d", nam, &pric, &yea, &mont, &nu);
n->kinds = ki;
n->doit.tdata.kind = kin;
strcpy(n->doit.tdata.prodata.name, nam);
n->doit.tdata.prodata.price = pric;
n->doit.tdata.rdata.out.year = yea;
n->doit.tdata.rdata.out.month = mont;
n->doit.tdata.rdata.out.num = nu;
ListInsert(L, n);//插入新的节点
n = n->next;
}
}
}
fclose(fp);//关闭文件
printf("录入完毕\n");
}
void freeList(LinkList* L) //释放分配的空间
{
LinkList* p, * q;
int n = 0;
p = L;
q = L->next;
while (n < ListLength(L))
{
n++;
free(p);
p = q;
if (p != NULL)
q = p->next;
}
printf("已释放\n");
}
int main()
{
LinkList* L;
L = (LinkList*)malloc(sizeof(LinkList));
L->next = NULL;
readdata(L);
int i;
system("cls"); //清新页面
printf(" =====================================================\n");
printf("--------------- 菜————单 -------------------------\n");
printf(" -----------------------------------------------------\n");
printf("|# #|\n");
printf("|#欢迎使用商店货物买卖系统第一版 #|\n");
printf("|#(由于技术原因只能操作不会损坏的商品销售) #|\n");
printf("|# #|\n");
printf("|# #|\n");
printf(" =====================================================\n");
printf("----------------商品基础信息--------------------------\n");
printf(" -----------------------------------------------------\n");
printf("|# (包含名称、价格) #|\n");
printf("|# #|\n");
printf("|# 1.查询物品信息 #|\n");
printf("|# #|\n");
printf("|# 2.删除物品信息 #|\n");
printf("|# #|\n");
printf("|# 3.添加物品信息 #|\n");
printf("|# #|\n");
printf("|# 4.列出全部物品清单 #|\n");
printf("|# #|\n");
printf("|#--------------------------------------------------#|\n");
printf(" =====================================================\n");
printf("--------------------货物流动情况----------------------\n");
printf(" -----------------------------------------------------\n");
printf("|# #|\n");
printf("|# 5.显示总入物品 #|\n");
printf("|# (包含名称、价格、更新年月、数量) #|\n");
printf("|# #|\n");
printf("|# 6.显示售出物品 #|\n");
printf("|# (包含名称、价格、售出年月、数量) #|\n");
printf("|# #|\n");
printf("|# 7.保存 #|\n");
printf("|#--------------------------------------------------#|\n");
printf("|# 0.退出 #|\n");
printf("------------------------------------------------------\n");
do {
printf("选择工作:");
scanf("%d", &i);
switch (i)
{
case 1:
finddata(L);
break;
case 2:
deletedata(L);
break;
case 3:
addproject(L);
break;
case 4:
displaypro(L);
break;
case 5:
displayin(L);
break;
case 6:
displayout(L);
break;
case 7:
savedata(L);
break;
case 0:
break;
default:
printf("请输入正确的选择\n");
break;
}
} while (i);
printf("程序已退出!");
freeList(L);
return 0;
}
(数据文件没有放在这里,那个没有代表意义)
我用的是vs2019,也关掉了SDL检查,但是scanf(“%c”,&ki)这段语句和fscanf(“%c”,&ki)这段语句在文件中检测到‘C’时还是运行不了,我猜测它运行不了的原因有二第一个就是我把addproject拆成两段,一段是只输入基础信息的函数,一段是输入流动数据的函数,但是发现前者可以正确运行,后者到了scanf(“%c”,&kin)的时候报错说出现间断;其二就是我在数据文件中手动输入几段进出货的数据,但是在后面操作输出进出货数据时候都没有结果,于是我在显示进货函数循环中写下printf(“1”)但是只执行了基础信息个数次数,说明链表中只有基础信息,流动信息没有加入进去,结合第一个原因,我认为是fscanf的原因。这是一个问题,还有就是在运行freeList这个函数的时候这个问题。
于是我回到主函数看以下尾节点是否赋了NULL值结果发现:
这里是这样的。所以现在不知道怎么改正。