数据结构课程设计+数据汇总超市Word格式.docx
《数据结构课程设计+数据汇总超市Word格式.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计+数据汇总超市Word格式.docx(35页珍藏版)》请在冰豆网上搜索。
构造n个单链表,每个链表保存一台收款机的销售记录,这n个单链表的头指针存放在一个指针数组中,通过数组的下标就可以知道是哪台收款机。
读取数据文件的记录,将所有的销售记录(数据文件中的全部记录)分解插入到n个单链表;
(3)编写以商品为单位的数据分类处理函数。
构造m个单链表,每个链表保存一种商品的销售记录,这m个单链表的头指针存放在一个指针数组中,通过数组的下标就可以知道是哪种商品。
读取数据文件的记录,将所有的销售记录(数据文件中的全部记录)分解插入到m个单链表;
(4)统计每台收款机的销售总额;
(5)以收款机为单位,将所有收款机按销售总额的递增顺序构造一个单链表并输出。
(6)以商品为单位,统计每种商品的销售总额。
(7)以商品为单位,将所有销售的商品按销售总额的递增顺序构造一个单链表并输出。
(8)设计一个菜单,具有插入数据记录、按收款机统计销售总额、按商品统计销售总额、退出系统等最基本的功能。
所采用的数据结构:
单链表
销售商品数据记录结构定义:
typedefstructGoods
{
intregNum;
//收款机编号
intgoodsNum;
//商品编号
intsalesVol;
//销售数量
doublesalesAmount;
//销售单价
}Goods;
typedefstructGoodsElemType;
//用于链表里的数据类型
单链表结点定义:
typedefstructNode
ElemTypedata;
//链表所存的数据
structNode*next;
//指向下一个结点的指针
}*LNode,*LinkList;
所设计的函数:
[1].将数据记录插入到文件data.dat最后的函数
intAddrecord(Goods*goods)
算法思想:
首先判断参数是否非法,非法则返回FAIL,否则以以二进制的append方式打开文件data.dat;
文件指针为空则打开失败返回FAIL,否则将数据记录写入文件,然后关闭文件,返回SUCCESS。
流程图:
[2].以收款机为单位的数据分类处理函数
LinkList*SortByReg(intn)
算法思想:
判断打开文件是否成功,失败则打印“打开文件失败”并返回FAIL,否则分配链表指针数组;
然后判断内存是否充足,不足则打印“内存不足”并返回FAIL,否则初始化n个收款机链表,并读相应记录,存到对应的收款机链表中的末尾结点,最后关闭文件,返回链表数组。
[3]统计每台收款机的销售总额
double*SumByReg(intn)
申请一个数组存储各台收款机的销售总额,申请不成功则打印“内存不足”并返回FAIL,否则调用SortByReg(n)函数得到分类好的收款机链表指针数组,判断指针数组是否为空,是则释放之前时申请的内存空间并返回NULL,否则初始化总额数组,并进行累计分析,之后释放收款机的链表内存,释放链表指针的内存,释放总额数组,返回总额amount
[4].以商品为单位的数据分类处理函数
LinkList*SortByGoods(intm)
然后判断内存是否充足,不足则打印“内存不足”并返回FAIL,否则初始化m个商品链表,并读相应记录,存到对应的商品链表中的末尾结点,最后关闭文件,返回链表数组。
[5].以商品为单位,统计每种商品的销售总额
double*SumByGoods(intm)
申请一个数组存储各种商品的销售总额,申请不成功则打印“内存不足”并返回FAIL,否则调用SortByGoods(m)函数得到分类好的各种商品的链表指针数组,判断指针数组是否为空,是则释放之前时申请的内存空间并返回NULL,否则初始化总额数组,并进行累计分析,之后释放收款机的链表内存,释放链表指针的内存,释放总额数组,返回总额amount
[6].设计一个菜单,具有插入数据记录、按收款机统计销售总额
voidRunMenu(void)
清除以前的无关输入,打印菜单,根据选择的菜单项进行相应的操作。
[7].用于输入一条新的记录
[8].GOODS的输出函数
程序运行结果:
1:
主程序运行,菜单打印
2插入数据记录
3.按收款机统计销售总额
4.按商品统计销售总额
5.按商品销售记录排序
6按收款机收款纪录排序
7退出系统
源程序:
#include<
stdio.h>
stdlib.h>
conio.h>
#defineSUCCESS1//操作成功
#defineFAIL0//操作失败
#defineallRegisters15
#defineallGoods30
//销售的商品数据记录
typedefstructGoods
//构造一个空的线性表
LinkListInitList(void)
LNodeHead;
Head=(LNode)malloc(sizeof(structNode));
//为链表的头结点分配空间
if(!
Head)
{
printf("
Outofspace!
"
);
returnNULL;
}
Head->
next=NULL;
returnHead;
//返回头结点,第一个结点head是不存任何数据的
}
//初始条件:
线性表L已存在。
操作结果:
返回线性表L的最后一个结点(尾结点)。
LNodeIsLast(LinkListL)
LNodeP=L->
next;
if(P)
while(P->
next!
=NULL)//遍历线性表L
P=P->
returnP;
//返回线性表L的最后一个结点
else
returnL;
//链表只有头结点,而它不存数据的
返回线性表L结点的个数。
intListLength(LinkListL)
intnum=0;
while(P)//累积线性表L结点的个数
num++;
returnnum;
//返回线性表L结点的个数
//构造一个数据域为X的新结点
LNodeNewLNode(ElemTypeX)
LNodeS;
S=(LNode)malloc(sizeof(structNode));
//为新结点分配空间
S)
S->
data=X;
returnS;
//返回新结点
销毁线性表L。
voidDestroyList(LinkList*L)
LNodeHead,P;
if(*L)//若线性表L已存在
Head=*L;
P=Head->
while(P!
=NULL)//把链表中除头结点外的所有结点释放
free(Head);
Head=P;
//释放头结点
*L=NULL;
线性表L中结点P已找到,新结点S已构造。
。
操作结果:
在该结点之后插入新结点X。
voidListInsert(LNodePre,LNodeS)
next=Pre->
Pre->
next=S;
//用于输入一条新的记录
//缺点就是没对输入的数据各种检查
//一旦输入字母就不行了
Goods*Newrecord(Goods*goods)
----------------------------\n"
"
请输入商品信息:
\n"
//收款台号,保证录入正确的数据
while
(1)
fflush(stdin);
printf("
收款机编号(1--%d):
#"
allRegisters);
scanf("
%d"
&
goods->
regNum);
if(goods->
regNum>
0&
&
goods->
regNum<
=allRegisters)
break;
//商品号
商品编号(1--%d):
allGoods);
goodsNum);
goodsNum>
goodsNum<
=allGoods)
//销售量
销售数量:
n="
scanf("
salesVol);
//销量单价
商品销售单价:
$"
%lf"
salesAmount);
//清除可能输入缓冲区
fflush(stdin);
returngoods;
//专为GOODS而写的输出函数
voidListPrint(LinkListL,doubleamount)
LNodenode;
inti;
intcount=ListLength(L);
if(L==NULL)
return;
//第一个结点不存记录,所以从第二个开始
node=L->
if(node==NULL)
//打印出表头
注意:
每打印5个记录,将会暂停,按enter继续!
!
收款机No(R).|商品No(G).|单价($)|销售数量(n)\n"
//将全部记录按格式打印出来
i=0;
while(i<
count)
{
R*%-15dG*%-13d$%-14.2lfn=%-13d\n"
node->
data.regNum,node->
data.goodsNum,node->
data.salesAmount,node->
data.salesVol);
if((i+1)%5==0)
getch();
i++;
node=node->
//这个就是打出总额了,Total则是记录的条数
销售总额=%lf,记录条数=%d\n"
amount,i);
//[1].将数据记录插入到文件data.dat最后的函数
FILE*ofp;
//非法参数
if(goods==NULL)
returnFAIL;
//以二进制的append方式打开文件data.dat
if((ofp=fopen("
data.dat"
"
ab"
))==NULL)
Openfail!
//把记录写入文件中
fwrite(goods,sizeof(structGoods),1,ofp);
//关闭文件
fclose(ofp);
returnSUCCESS;
//[2].编写以收款机为单位的数据分类处理函数
inti,count;
FILE*ifp;
Goodstemp;
LinkList*regArr;
//收款机的链表数组
if((ifp=fopen("
rb"
OpenFail.\n"
//分配链表指针数组
regArr=(LinkList*)malloc(n*sizeof(LinkList));
if(regArr==NULL)
Notenoughmemory\n"
//n个收款机链表初始化
for(i=0;
i<
n;
i++)
regArr[i]=NULL;
//开始根据收款机的编号将所读的记录进行分类
//注意数组下标是从0开始,而收款机是从1开始数的
while
(1)
//读相应的记录,正确读取时count为所读的字节数
count=fread(&
temp,sizeof(structGoods),1,ifp);
//出错或是到文件尾了
if(count!
=1)
//第一次要初始化链表
if(regArr[temp.regNum-1]==NULL)
regArr[temp.regNum-1]=InitList();
//存到对应的收款机链表中的末尾结点
ListInsert(IsLast(regArr[temp.regNum-1]),NewLNode(temp));
fclose(ifp);
returnregArr;
//[3]统计每台收款机的销售总额
inti,recs;
double*amount;
//申请一个数组存储各台收款机的销售总额
if((amount=(double*)malloc(n*sizeof(double)))==NULL)
Notenoughmemory!
//得到了分类好的收款机链表指针数组
regArr=SortByReg(n);
free(amount);
//释放之前申请的内存
returnNULL;
//初始化总额数组
amount[i]=0;
//进行分析累加
if(regArr[i]==NULL)
continue;
//链表头是不存任何数据的
node=regArr[i]->
//链表是空的
if((recs=ListLength(regArr[i]))==0)
//遍历一个收款机链表里有的所有记录
while(recs-->
0)
{
//将该台收款机销售的商品记录的总额进行累加
amount[i]+=node->
data.salesAmount*node->
data.salesVol;
node=node->
}
//释放收款机的链表内存
//打印出后再释放内存
ListPrint(regArr[i],amount[i]);
DestroyList(&
regArr[i]);
//释放链表指针头的内存
free(regArr);
//释放总额数组
free(amount);
returnamount;
//[4]排序收款机销售总额
double*PaixuByReg(intn)
inti,recs,k,l,temp;
for(k=0;
k<
i-1;
k++)
for(l=k+1;
l<
l++)
if(amount[k]>
amount[l])
temp=amount[k];
amount[k]=amount[l];
amount[l]=temp;
排序后的数组为\n"
returna