学生个人生活费管理系统2.docx
《学生个人生活费管理系统2.docx》由会员分享,可在线阅读,更多相关《学生个人生活费管理系统2.docx(18页珍藏版)》请在冰豆网上搜索。
![学生个人生活费管理系统2.docx](https://file1.bdocx.com/fileroot1/2022-11/29/9db81c89-9013-4e4b-9bca-526aa088eb7e/9db81c89-9013-4e4b-9bca-526aa088eb7e1.gif)
学生个人生活费管理系统2
学生个人生活费管理系统
(2)
目录
1需求分析
1.1问题描述5
1.2输入数据要求5
1.3输出数据要求6
1.4开发环境和工具6
2总体设计7
2.1总体设计思路7
2.2模块结构图7
2.3模块说明8
3详细设计10
3.1数据类型定义10
3.2打开模块实现13
3.3更新模块实现16
3.4统计模块实现…………………………………………………………………………16
4测试与调试……………………………………………………………………………………16
4.1测试………………………………………………………………………………………18
4.2调试………………………………………………………………………………………18
5.结论19
结束语19
参考文献
附录
附录2-源程序21
1需求分析
1.1问题描述
随着社会经济的发展,大学生已经成为这个社会上一个很重要的团体,而他们的消费情况也越来越多的被更多的人关注,大学生自己也应当管理好自己的消费内容,让自己的消费更加合理化,提高自己生活的质量。
在这种情况下,就需要一个软消费表信息:
编号,时间,类别,品名,单价,数量,金额
对学生每天的消费情况作一个较为详细的统计,该系统可以实现由计算机代替人工执行一些复杂而且较为繁琐的操作,从而使大学生们能够更为便捷地管理自己的消费,也为其他的一些调查研究提供了方便。
1.2输入数据要求
根据日常生活中,学生个人财务情况,实现一个个人生活费的财务管理软件。
功能有:
1登陆。
只有在输入正确的用户名和密码之后才能使用软件。
2修改已有信息。
收支信息应该包括收支日期(年月日),收入或者支出,金额,收入来源或者支出目的,账户余额等。
可借用学生个人生活费管理系统
(1)中的添加功能。
3能够查询某天或者某月的收支情况。
1.3输出数据要求
打开:
显示文件中的所有消费记录,提供分页显示
保存:
将消费表的更新结果存入文件
更新:
可插入、删除、修改各消费记录
查找:
按时间,类别、品名查找消费记录
排序:
按时间,类别,金额
统计:
求各类别消费品的总金额,求各月的消费总金额,求各年消费总金额
1.4开发环境和工具
开发环境:
Windows7
开发工具:
VisualC++6.0
2总体设计
2.1总体设计思路
1.设计思路
个人消费系统管理包含的操作有:
打开、保存、更新、查找、排序和统计。
在程序开始运行的时候从文件加载已有数据,并输出可以进行的操作提供给用户,
1、打开:
显示文件中的所有消费记录,通过取模运算提供分页显示功能
2、保存:
以wb模式打开文件,将修改的内容写入文件
3、更新:
可插入、删除、修改各消费记录
4、查找:
按时间,类别、品名查找消费记录
5、排序:
按时间,类别,金额
6、统计:
分别按类别、月、年统计消费品的总金额
2.数据存储
为了操作的方便,用typedef自定义了一些数据类型,其中包含一个长度为MAX的数组,用来存放从文件中读取的数据。
2.2模块结构图
根据需求将系统划分为六个功能模块,函数之间的调用关系如图2.1所示。
图2.1个人消费系统的模块结构图
Calledit:
在主函数的控制下,调用各个模块
1)ShowRec:
输出已存在的记录。
2)SaveRec:
保存更新的内容。
3)UpdateRec:
按一定的方式更新记录。
这个模块下包含三个子模块插入:
Insert
删除:
DeleteByNum
修改:
Modify
4)FindRec:
按一定的方式查找记录。
这个模块下也包含三个子模块按日期查找:
FindBytime
按类型查找:
FindByType
按名称查找:
FindByName
5)SortRec:
按一定的方式查找记录。
这个模块下也包含三个子模块按日期查找:
SortBytime
按类型查找:
SortByType
按名称查找:
SortBySum
6)ShowTotal:
显示各种统计的结果
2.3模块说明
(以从上至下,从左至右的顺序说明)
2.3.1:
打开模块:
自定义函数:
ShowRec()
函数功能:
输出已存在的历史记录
无参函数:
无参数
2.3.2:
更新模块:
自定义函数:
UpdateRec()
函数功能:
可对输入数据实现插入,删除,修改操作。
无参函数:
void类型,无返回值。
调用Insert()函数,Delete()函数和Modify()
2.3.2.1插入模块:
自定义函数:
Insert()
函数功能:
实现插入新的信息并保存到记录中,其中插入的数据最后金额可以自己运算出来,插入的记录保存在尾部。
无参函数:
返回值为int类型
2.3.2.2删除模块:
自定义函数;RemoveByNum(intnum)
函数功能:
对所选信息按编号删除,删除过后,后面记录到编号将全部减1,记录的编号即下标。
输入参数:
int类型,返回值是int类型。
num--int类型,表示define.h文件中定义的类型Rec_Con中数组record[]的下标,删除过后,后面记录到编号将全部减1,记录的编号即下标。
后面的记录全部向前移动一个距离。
2.3.2.3修改模块:
自定义修改函数:
Modify()
函数功能:
按名称修改记录,先判断要查找的名称所对应的记录是否存在,不存在则直接返回。
无参函数:
返回值为int型
2.3.3:
统计模块:
函数原型:
ShowTotal()
函数功能:
显示统计结果
无参函数:
void类型,无返回值。
2.3.3.1按类型统计:
ShowType()
函数功能:
按类型显示统计结果
无参函数;void类型,无返回值。
2.3.3.2按月显示统计结果:
函数原型:
ShowMonth()
函数功能:
忽略了年,按月显示统计结果
无参函数:
void类型,无返回值。
2.3.3.3按年显示统计结果:
函数原型:
ShowYear()
函数功能:
按年显示统计结果
无参函数:
void类型,无返回值。
3详细设计
3.1数据类型定义
关键数据都定义在define.h里
#defineMAX100//人为定义的一个上限
typedefstruct//定义记录结构体,并重新命名类型名
{
intnum;//编号
chartimes[11];//时间
chartypes[20];//类别
charname[20];//品名
doubleprice;//单价
intquantity;//数量
doublesum;//金额
}Rec;
typedefstruct//定义操作结构体,并重新命名类型名
{
Recrecord[MAX+1];//定义结构体变量,可操作的记录总数,下标为0和MAX不存放记录
inttotal_count;//整型变量,记录总数
}Rec_Con,*PRec_Con;
union{//定义一个查找时使用的共用体
chartimes[11];//存放按时间查找时输入的时间
chartypes[20];//存放按类型查找时输入的类型
charname[20];//存放按名称查找时输入的名称
}found;
//下面三个变量都是全局变量
FILE*fp;//定义文件指针
Rec_Conrs;//用来定义变量,避免了动态分配中的安全问题
PRec_Conrecords=&rs;//定义操作指针变量
inttype_count=0;//记录里相关的类型数目
intyear_count=0;//记录里相关的年数目
char*ptype[MAX+1];//字符型变量,记录里相关的类型
charpyear[MAX+1][5];//字符型变量,记录里相关的年
chartmp[5];//字符型变量,取年份所用
chartmp01[5],tmp02[5];//存放Get4的返回值,在比较时使用
charc;//字符型变量,临时使用变量,没有固定的限制
3.2ShowRec模块实现
1.算法思想:
按编号,时间,类别,品名,单价,数量,金额的顺序打开文件,并显示结果。
其中提供分页显示功能。
2.具体实现:
voidOpenFile()//打开文件函数,以二进制append形式操作
{
if((fp=fopen("consum","ab+"))==NULL)
{
printf("Fileopenfail!
\n");
return;
}
}
voidShowI(inti)//根据i值输出记录
{
printf("记录:
\n\n");
printf("\n编号时间类别品名单价数量金额\n");
printf("%-5d%-10s%15s%15s%8.2f%5d%8.2f\n",records->record[i].num,records->record[i].times,records->record[i].types,records->record[i].name,records->record[i].price,records->record[i].quantity,records->record[i].sum);
}
intShowRec()//显示所有记录
{
inti;
for(i=1;i<=records->total_count;i++)
{
printf("%-5d%-10s%15s%15s%8.2f%5d%8.2f\n",records->record[i].num,records->record[i].times,records->record[i].types,records->record[i].name,records->record[i].price,records->record[i].quantity,records->record[i].sum);
if((i%10)==0)//实现分页功能
{
printf("Pressanykeyshownextpage……\n");
getchar();
//cls();
}
}
return1;
}
3.3更新模三个块:
更新包括内容;插入,删除,查找
1.算法思想:
利用三个自定义函数:
intInsert()//插入函数,intDeleteByNum()//按编号删除,intModify()//按名称修改记录。
插入过程用MAX控制插入信息的范围;删除时按编号删除,删除过后,后面记录到编号将全部减1,记录的编号即下标。
修改时先利用intFindByName(char*name);按名称查找记录函数,找到相关信息,若无此信息直接跳转,否则修改。
2.具体实现:
intInsert()//插入函数
{
if(records->total_count==(MAX-1))
{
printf("数据已达可控范围,不能再插入!
\n");
return0;
}
inti=(++records->total_count);
records->record[i].num=i;//编号是连续的,
printf("\n时间类别品名单价数量金额\n");
scanf("%s%s%s%lf%d",records->record[i].times,records->record[i].types,records->record[i].name,&records->record[i].price,&records->record[i].quantity);
if(strlen(records->record[i].times)!
=10||records->record[i].times[4]!
='-'||records->record[i].times[7]!
='-')//简单的判断一下日期是否符合格式要求
{
printf("时间格式错误,请重试!
\n");
records->total_count--;
return0;
}
records->record[i].sum=records->record[i].price*records->record[i].quantity;//金额是计算所得
#ifdefDEBUG
ShowI(i);
#endif
return1;
}
intRemoveByNum(intnum)//删除过后,后面记录到编号将全部减1,记录的编号即下标
{
inti;
if(num<1||num>records->total_count)
{
printf("位置错误!
\n");
return0;
}
for(i=num;itotal_count;i++)//i后面的记录全部向前移动一个距离
{
records->record[i].num=records->record[i+1].num-1;
strcpy(records->record[i].times,records->record[i+1].times);
strcpy(records->record[i].types,records->record[i+1].types);
strcpy(records->record[i].name,records->record[i+1].name);
records->record[i].price=records->record[i+1].price;
records->record[i].quantity=records->record[i+1].quantity;
records->record[i].sum=records->record[i+1].sum;
}
return1;
}
intDeleteByNum()//按编号删除
{
intnum;
printf("请输入要删除记录的编号:
");
scanf("%d",&num);
if(!
(RemoveByNum(num)))
{
printf("程序执行错误,删除失败!
\n");
return0;
}
else
return1;
}
intFindByName(char*name);//声明按名称查找记录函数,下面就要使用到
intModify()//按名称修改记录
{
inti;
charnames[20];
printf("请输入要修改的记录名称:
");
scanf("%s",names);
i=FindByName(names);
if(!
i)//判断要查找的名称所对应的记录是否存在,不存在则直接跳转
return0;
printf("请输入所需信息:
\n");
printf("\n时间类别品名单价数量金额\n");
scanf("%s%s%s%lf%d",records->record[i].times,records->record[i].types,records->record[i].name,&records->record[i].price,&records->record[i].quantity);
records->record[i].sum=records->record[i].price*records->record[i].quantity;
return1;
}
3.4ShowTotal模块实现
ShowTotal包括三种方式:
类型、月、年,以类型为例说明
1、算法思想
为确保不会溢出,保存统计结果的total数组定义长度为MAX,接下来对记录集进行遍历,并与ptype[]数组中统计的类型进行比对,按照对应的下标将统计结果加到total[]数组中,这样做便于输出时一一对应。
(复杂算法用流程图辅助说明)
2、具体实现
(给出实现算法的关键代码)
按类型显示统计结果
voidShowType(){
inti=1,j=0;
doubletotal[MAX]={0.0};//定义保存统计结果的数组
while(i<=records->total_count&&jif(strcmp(ptype[j],records->record[i].types)==0){
total[j]+=records->record[i].sum;
i++;
}
elsej++;
}
//输出统计结果
printf("按类型统计结果如下:
\n");
for(i=0;iprintf("%s:
\t%8.2f\n",ptype[i],total[i]);
}
printf("\n");
}
4.调试与测试
4.1调试
说是最艰巨的任务。
调试的任务是及时改正测试过程中发现的软件错误。
具体地也调试是软件开发过程中的一个重要环节,也是最复杂,对软件开发者者来说,调试过程由两个步骤组成,它从表示程序中存在错误的某迹象开始,首先确定错误的准确位置,也就是找出哪个模块或哪个语句引起的错误。
然后仔细研究推断代码以确定问题的原因,并设法改正。
调试过程主要是运行编制好的程序,然后遇到错误后根据系统的提示,找到相关的问题所在。
本系统调试过程中遇到问题、原因和解决方法如下面介绍。
(1)程序不能运行
定义的指针,很多次引用,过个函数里面,定义的不明确,造成错误连连发生。
(2)不能正确输出信息,有乱码现象
原因是键入信息的时候,没有一一对应,逗号的位置不正确,后来,用的是信息逐一输入,保证了信息的一一对应和高度的准确性,使程序可以正常运行。
(3)程序运行途中,出现错误,被迫中止
其中定义字符数组,却没有定义长度,导致定义类型变成了字符型,而不能接受字符串,因此出现了错误。
4.2测试
软件测试是软件生存期中的一个重要阶段,是软件质量保证的关键步骤从用户的角度来看,普遍希望通过软件测试暴露软件中隐藏的错误和缺陷,所以软件测试应该是“为了发现错误而执行程序的过程”。
或者说,软件测试应该根据软件开发各阶段的规格说明和程序的内部结构而精心设计一批测试用例(即输入数据及其预期的输出结果),并利用这些测试用例去运行程序,以发现程序错误或缺陷。
过度测试则会浪费许多宝贵的资源。
到测试后期,即使找到了错误,然而付出了过高的代价。
5.结论
课程设计顺利完成,题目所要求的功能也都一一实现,可以对职工信息进行添加,修改,删除,查询,模糊查询,按条件查询,存储至文本文件等,在通常情况下,可以良好的运作。
不过这个程序还有些不够完善,例如有时候,输出的结果会因为字符的长短,与上面的提示栏对不上。
而且,由于自己英语的不够特别好,后几个功能不知道该怎么翻译,就直接写的汉字,显得程序主菜单有点乱,以后会加强英语,好好规划编程。
结束语
为期七天的的软件综合课程设计实习终于顺利完成,在这期间,我学到了很多课堂上学不到的东西,而且,将所学付之于实践,理论联系实际,是令我很兴奋的,但同时也感觉到了难度。
对C语言,有了更深一步的了解,并且培养出了良好的思考方式,对于编程。
虽然困难很多,问题出现的也很多,但好在,顺利完成任务了,很有成就感。
.
[1]参考文献
谭浩强.C语言程序设计(第三版).北京:
清华大学出版社,2005.7
附录1,
附录二源程序#include
#defineN10
structstudent
{
charnum[10];
charname[20];
floatscore[3];
floatsum;
floataver;
}stu[N];
voidmain()
{
printf("**********madebyB14140104**********\n\n");
printf("******学生个人生活费管理系统
(2)******\n\n\n");
voidcount(structstudentstu[]);
voidsort(structstudentstu[]);
voidfind(structstudentstu[]);
inti;
floattemp;
for(i=0;i{
printf("请输入第%d位同学的支出信息:
\n",i+1);
printf("学号:
");
gets(stu[i].num);
printf("名字:
");
gets(stu[i].name);
printf("支出1:
");
scanf("%f",&temp);
stu[i].score[0]=temp;
printf("支出2:
");
scanf("%f",&temp);
stu[i].score[1]=temp;
printf("支出3:
");
scanf("%f",&temp);
getchar();
stu[i].score[2]=temp;
}
count(stu);
printf("\n");
sort(stu);
printf("\n");
find(stu);
}
voidcount(structstudentstu[])
{
floatsum,aver;
inti,j;
for(i=0;i{
sum=0;
for(j=0;j<3;j++)
sum+=stu[i].score[j];
aver=sum/3.0;
stu[i].sum=sum;
stu[i].aver=aver;
}
printf("学号姓名总支出平均支出\n");
for(i=0;iprintf("%-8s%-10s%-9.2f%-9.2f\n",stu[i].num,stu[i].name,stu[i].sum,stu[i].aver);
}
voidsort(structstudentstu[])
{
inti,j,k;
structstudenttemp;
for(i=0;i{