个人账单管理系统数据结构课程设计.docx
《个人账单管理系统数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《个人账单管理系统数据结构课程设计.docx(18页珍藏版)》请在冰豆网上搜索。
个人账单管理系统数据结构课程设计
沈阳航空航天大学
课程设计报告
课程设计名称:
数据结构课程设计
课程设计题目:
个人账簿管理系统
1课程设计介绍
1.1课程设计内容
个人账簿管理系统记录某人每月地全部收入及各项开支情况,包括食品消费,房租,子女教育费,水电费,医疗费,储蓄等.进入系统后可以输入和修改某月地收支情况,可以对每月地开支从小到大进行排序,可以根据输入地月份查询每月地收支情况.
1.2课程设计要求
1.采用链表结构管理收支情况,并能够保存到文件中;
2.完成对每月地开支排序,以及完成系统查询功能;
3.独立完成系统地设计,编码和调试;
4.系统利用C语言实现;
5.按照课程设计规范书写课程设计报告.
2课程设计原理
2.1课设题目粗略分析
根据课设题目要求,拟将整体程序分为五大模块.以下是五个模块地大体分析:
1.账簿信息输入:
该模块中,以带头结点地链表为账单信息地存储结构,输入各项开支地数据.
2.账簿信息排序:
该模块中,将针对每月地消费总额进行从小到大地顺序进行排序.
3.账簿信息查询:
该模块中,将输入或已排序账单进行按所输入地日期进行查询并将查询结果打印至屏幕,供人阅读.
4.账单信息更改:
进入该模块,进行信息地更改或添加.
5.账单信息保存:
该模块将账单信息以文本文档保存到磁盘中.
2.2原理图介绍
2.2.1功能模块图
图2.1功能模块图
2.2.2流程图分析
1.账单建立时调用jianli()函数,而在在jianli()中调用tianjia()函数;账单地头结点地申请工作已在主函数中完成,所以在整个建立账单地过程中核心内容是:
将新地账单信息链接到已存在地账单后面;tianjia()函数流程图如图2.2所示.
图2.2账单信息添加函数流程图
2.在对账单信息进行排序地过程中,采用地方法是:
首先将账单中支出最大和最小地两个结点寻找出来并按从小到大地顺序连接到一个新申请地头结点上;再将原函数地各结点插入到新地链表中,最终新地链表就成为了排序后地新账单.paixu()函数流程图如图2.3所示.
图2.3排序函数流程图
3.进入账单信息查询部分,程序根据输入地日期进行逐一比较,若存在该日期地账单信息,程序输出相应地账单信息,若不存在该日期地账单信息,系统提示用户还未录入该日期地账单信息.账单查询函数流程图如图2.4所示.
图2.4查询函数流程图
4.进入账单更改部分,程序将用户输入地需更改地账单日期与已存在地账单日期进行逐步比对,对日期完全相同地账单信息进行更改,若不存在该日期地账单信息,程序提示用户是否马上进行添加.流程图如图2.5所示.
图2.5账单信息更改流程图
5.进入账单保存部分,用户对建立地账单以文本文档地形式保存到磁盘中,账单信息保存函数流程图如图2.6所示.
图2.6保存账单信息函数流程图
3数据结构分析
3.1存储结构
主要存储结构:
带头结点地单向链表存储结构.
typedefstructMYBILL//链表结点结构
{
longdate。
//日期信息
longfood。
//食品消费
longfangzu。
//房租费用
longjiaoyu。
//子女教育费
longshuidian。
//水电费
longyiliao。
//医疗费
longchuxu。
//储蓄
longpay。
//总支出
longincome。
//总收入
structMYBILL*next。
//指向下一结点地指针
}MYBILL,bill。
3.2算法描述
1.建立单向链表,用来存储账单信息:
首先分别输入将要建立账单地年份及月份,年份地合理范围定为所有正整数,当年份输入为非合理数字时结束对账单地录入;月份地合理范围为1至12,当输入不属于该范围地月份数据时,程序会重新进行年份和月份地录入;录入日期数据后,进行其余信息地录入.
void*tianjia(MYBILL*head)//向原链表添加新地链表结点
{inti,j。
//定义年份和月份变量
MYBILL*p,*tail。
//定义结构体类型指针
p=head。
//将指针p初始化为head
while(p->next!
=NULL)//判断账单链表是否为仅含空头结点地链表
{p=p->next。
//将指针p向后移动一个单位
}
printf("\n\t输入您要建立账单地年份,当输入非正数时结束输入!
\n\t")。
scanf("%ld",&i)。
//输入年份数据
while(i>0)//判断输入地年份是否为合理数据
{printf("\n\t输入您要建立账单地月份\n\t")。
scanf("%d",&j)。
//输入月份数据
if(j>0&&j<13)//判断输入地月份数据是否为合理数据
{tail=(bill*)malloc(sizeof(bill))。
//申请一个结点空间
if(tail==NULL)
{printf("存储空间分配失败!
\n")。
return(NULL)。
}
tail->date=100*i+j。
//将年份和月份为转为一长整数字存储
tail->next=NULL。
//新结点地指针域指向空
printf("\n\t输入食品费用:
\t")。
scanf("%ld",&tail->food)。
//输入食品费用
printf("\n\t输入房租:
\t")。
scanf("%ld",&tail->fangzu)。
//输入房租费用
printf("\n\t输入子女教育费:
")。
scanf("%ld",&tail->jiaoyu)。
//输入子女教育费
printf("\n\t输入水电费:
\t")。
scanf("%ld",&tail->shuidian)。
//输入水电费
printf("\n\t输入医疗费:
\t")。
scanf("%ld",&tail->yiliao)。
//输入医疗费
printf("\n\t输入储蓄:
\t")。
scanf("%ld",&tail->chuxu)。
//输入存储
printf("\n\t输入总收入:
\t")。
scanf("%ld",&tail->income)。
//输入总收入tail->pay=tail->food+tail->fangzu+tail->jiaoyu+tail->shuidian+tail->yiliao。
//将所有支出相加作为总支出
p->next=tail。
//将新申请地结点链接到原链表地最尾端
p=p->next。
//指针p向后移动一个单位
}
elseprintf("\n\t输入月份不合理,请重新输入!
\n\t")。
printf("\n\t输入您要建立账单地年份,当输入非正数时结束输入!
\n\t")。
scanf("%ld",&i)。
//输入年份信息
}
}
MYBILL*jianli(MYBILL*head)//建立账单链表函数
{
MYBILL*head。
//定义结构体类型指针
tianjia(head)。
//调用子函数tianjia()
if(head->next!
=NULL)//判断账单链表是否为仅含空头结点地链表
printf("\n\t\t\t===========账单录入成功!
===========\n\n")。
else
printf("\n\t\t\t===========没有账单录入!
===========\n\n")。
returnhead。
//返回头指针
}
2.账单排序,排序方法采用将所有数据中最小和最大值挑选出来,再将处于这两个数据中间位置地其他数据进行插入.
MYBILL*paixu(MYBILL*head)//账单信息排序函数
{longmin,max。
//定义两个变量对两个最值数据进行标记
inti,j。
//年份月份定义
MYBILL*q,*t,*p,*head1。
//定义结构体类型指针
q=head->next。
//将q初始化为head->next
if(head->next!
=NULL)//判断链表是否为只含头结点地空链表
{min=q->pay。
//第一结链表支出最少
t=head。
//初始化指针t地值
p=q。
//初始化p地值
while(q->next!
=NULL)//月支出最小结点为新排序账单地第一个结点
{if(min>q->next->pay)//比较q地pay和q->next地pay大小
{min=q->next->pay。
//如果p->next地pay小将其值赋给min
p=q->next。
//用p标记支出最少地结点
t=q。
//用t标记支出最少地结点地上一结点
}以便摘除支出最少地结点
q=q->next。
//将指针q向后移动一个单位
}
t->next=p->next。
//将支出最少地结点摘下
head1=(bill*)malloc(sizeof(bill))。
//申请排序后链表头结点
head1->next=p。
//将最小支出连接到新链表后作为第一个结点
p->next=NULL。
//将新链表尾端指向空
q=head->next。
//再次将q指向原链表头指针地后一结点
if(q!
=NULL)//判断链表是否为只含头结点地空链表
{max=q->pay。
//月支出最大结点为新排序账单地第二个结点
t=head。
//初始化指针t地值
p=q。
//初始化p地值
while(q->next!
=NULL)//判断是否只存在最大最小支出外
{if(maxnext->pay)//比较max与q->next->pay地大小
{max=q->next->pay。
//如果p->next地pay小将其值赋给max
p=q->next。
//用指针p标记支出最多地结点
t=q。
//用指针t标记支出最大地结点
}以便摘除支出最多地结点
q=q->next。
//将指针q向后移动一个单位长度
}
t->next=p->next。
//摘掉支出最大地结点
head1->next->next=p。
//将最大支出连接到新链表后
p->next=NULL。
//将新链表尾指向空
q=head->next。
//第三次初始化指针q
while(q!
=NULL)//依次从原表中摘取结点插入到新表,使其有序
{head->next=q->next。
//将q结点摘除
p=head1->next。
//初始化p指向新链表头结点地下一结点
while(q->pay>p->next->pay)//比较原链表与新链表支出
{p=p->next。
//将新链表地p结点向后移动
}
q->next=p->next。
//将q结点链接到p后
p->next=q。
q=head->next。
//将q重新置于head后结点上