江西师范大学本科生课程论文封面课程名称C语言课程设计类别: C.本科生组长:黄金峰组员:谢熊飞吴云清王伟林梦婷日期: 2014年7月7日课程设计评语对课程论文的评语:平时成绩:课程论文成绩:总成绩:评阅人签名:注:1、无评阅人签名成绩无效;2、必须用钢笔或圆珠笔批阅,用铅笔阅卷无效;3、如有平时成绩,必须在上面评分表中标出,并计算入总成绩。
目录课程设计评语 (2)目录 (3)1.课程论文题目.............................................................................................. 错误!未定义书签。
2.程序设计思路.............................................................................................. 错误!未定义书签。
3.功能模块图 (6)4.数据结构设计 (6)5.算法设计...................................................................................................... 错误!未定义书签。
6.程序代码...................................................................................................... 错误!未定义书签。
7.程序运行结果.............................................................................................. 错误!未定义书签。
8.编程中遇到的困难及解决方法.. (30)9.总结心得及良好建议 (30)10.致谢 (31)一.课程论文题目职工工资信息管理系统【要求】该系统能够实现工资信息管理.系统包括录入,浏览,查询,统计等功能.其中录入功能要求能够添加新的工资信息到文件;浏览功能要求能按照工资卡号,姓名分类浏览,提供分屏显示;有排序功能,排序后按照工资卡号升序或实发工资降序输出;查询功能要求能够按照工资卡号,姓名查询;统计功能要求能够按照月份累计统计某职工在某时间段实发工资总金额。
【提示】1、文件中一行数据对应一个职工工资信息。
2、工资信息的数据结构采用结构体数组,一个数组元素对应一条工资单记录。
3、工资单信息包括工资卡号、姓名、月份、应发工资、税费、电费、税金、实发工资等。
4、实发工资=应发工资—税费—电费—税金,其中税金计算方法为:(1)应发工资<800元,税金=0(2)800<应发工资<1400元,税金=(应发工资—800)*5%(3)应发工资>1400元,税金=(应发工资—1400)*10%二.程序设计思路1、设计思路(1)根据题目要求,应该把职工工资信息用结构体形式输入,在定义一个全局变量和文件指针进行整个程序的运行,然后把职工工资信息送到文件中,所以应该提供一个结构体和文件的输入输出等操作;(2)在程序中需实现职工工资浏览、查询、统计等功能的操作,所以需要建立相应的功能模块来实现;(3)另外还需要提供键盘式选择菜单实现功能,在运行时达到所要的目的。
2、总体设计整个系统可以分为信息输入、信息新增、信息浏览、信息排序和信息查询五个主要模块。
3、详细设计(1)工资信息采用结构体数组:struct list{int num; //工资卡号char name[20]; //姓名int month; //月份int salary1; //应发工资int water; //水费int electrisity; //电费float fax; //税金float salary2; //实发工资}list[N]; //list[N]中每个数组元素对应一个职工工资信息(2)输入模块按照工资卡号、姓名、月份、应发工资、水费、电费的顺序输入信息,税金和实发工资根据输入的信息进行计算得到,这些信息被录入到文件中。
文件操作函数:fopen,fwrite,fclose.税金的计算:if(应发工资<=800)税金=0;else if (应发工资>800&&应发工资<=1400)税金=(应发工资-800)*5%;else if (应发工资>1400)税金=(应发工资-1400)*10%;实发工资=应发工资-水费-电费-税金。
(3)新增模块增加新的职工工资信息,从键盘输入并逐条写到原来的输入文件中,采用追加而不是覆盖的方式(以“ab”方式打开文件)。
(4)浏览模块调用排序模块的排序功能,可以浏览排序后的所有职工信息。
(5)排序模块排序模块提供菜单选择,实现按照工资卡号升序、实发工资升序排序。
排序方法可以选择冒泡排序、插入排序、选择排序等,本系统用的是冒泡排序。
(6)查询模块实现按照工资卡号和姓名的查询,采用基本的查找方法即可。
三.功能模块图四. 数据结构设计系统用将职工各项信息以结构体类型struct list 来定义,它包括num ,name[20],month,salary1,water,electricity,fax,salaly2等不同类型的数据项,同时定义了结构体数组,包括N 个数组元素,对应N 个职工,每一个元素用来存放一个职工的数据;每个职工的信息以结构体方式从内存和磁盘文件中进行存储和导出。
以结构体方式来整合职工的不同信息,将不同的数据组合成一个有机整体,非常方便程序的调用。
五.算法设计1、主函数主函数一般设计比较简单,只提供输入、处理和输出部分的函数调用。
各功能模块用菜单方式选择。
[流程图]职工工资信息管理系统主菜单menu()输入模块enter() 新增模块add ()浏览模块browse()排序模块order()按姓名查询search_1()查询模块search()按工资卡号查询search_2() 退出exit(0)按实发工资排序order_2() 按工资卡号排序order_1()N Y#include<stdio.h> #include<string.h> #include<conio.h> #include<stdlib.h> #define N 50void main() /***************主函数***************/ {void menu(); /*声明菜单函数*/ menu(); /*调用菜单函数*/ }void menu() /***************菜单函数***************/ {void enter(); void add(); void browse(); void search(); void order(); int n,w1; do {puts("\t\t*********************MENU*************************\n\n"); puts("\t\t\t 1.Enter "); puts("\t\t\t 2.Add");puts("\t\t\t 3.browse all"); puts("\t\t\t 4.Search "); puts("\t\t\t 5.Order "); puts("\t\t\t 6.Exit");puts("\n\n\t\t*************************************************\n"); printf("Choice your number(1-6):[ ]\b\b");开 始显示一系列的功能选择输入n ,判断n 是否是0到6 根据n 值调用各功能模块scanf("%d",&n);if(n<1||n>6) /*对选择数字作判断*/{w1=1;getchar();}else w1=0;}while(w1==1);switch(n) /*选择功能*/{case 1:enter();break; /*输入模块*/case 2:add();break; /*追加模块*/case 3:browse();break; /*浏览模块*/case 4:search();break; /*查找模块*/case 5:order();break; /*排序模块*/case 6:exit(0);}}2、各功能模块设计(1)输入模块[数据结构]把职工的卡号、月份应发工资、水费、电费、税金、实发工资作为结构体成员,如果存放若干个职工信息就用结构体数组。
struct list{int num;char name[20];int month;int salary1;int water;int electrisity;float fax;float salary2;}list[N]; /*list[N]中每个数组元素对应一个职工*/[流程图]1 2/***************输入模块***************/ void enter() /*输入模块*/ {void printf_back(); void save(int n); void input(int i); int i,n;printf("how many workers (0-%d)?:",N-1); scanf("%d",&n);printf("\n enter date now\n\n"); for(i=0;i<n;i++) {printf("\n input %dth worker record.\n",i+1); input(i); /*调用输入函数*/ }if(i!=0)save(n); /*调用保存函数*/printf_back(); /*一个任务结束时让用户选择是浏览还是返回*/ }⑵ 追加模块[需求分析]该模块的功能是用户需要增加新的职工记录,请从键盘输入并逐条写到原来的输入文件中是追加不是覆盖.[流程图]开 始输入职工数目 输入各项信息储存职工信息 返回? 主菜单 浏览职工信息12[程序]/***************追加模块***************/ void add() /*追加模块*/ {void printf_back(); int i,n,m,k; int load(); void save(int n); void input(int i); FILE *fp; n=load();printf("how many workers are you want to add(0-%d)?:",N-1-n); scanf("%d",&m); /*输入要追加的个数*/ k=m+n;for(i=n+1;i<=k;i++) {printf("\n input %dth workers record.\n",i-n); input(i); /*调用输入函数*/ }fp=fopen("workers.txt","ab") /*以ab 方式打开文件,追加保存*/; for(i=n+1;i<=k;i++) /*输出到文件*/ fwrite(&list[i],sizeof(struct list),1,fp);fclose(fp);printf_back(); /*一个任务结束时让用户选择是浏览还是返回*/}开 始输入新增职工数目输入新职工信息储存输入信息返回?浏览职工信息主菜单⑶浏览模块[需求分析]该模块的功能是显示所有职工记录工资信息.[流程图]显示职工工资记录(10个一屏)按任意键显示下一屏按任意键返回主菜单[程序]/***************浏览(全部)模块***************/void browse() /*浏览模块*/{void printf_one(int i);void printf_face();int load();void menu();int i,n;n=load(); /*加载记录*/printf_face(); /*调用显示数据结构项目函数*/for(i=0;i<n;i++){if((i!=0)&&(i%10==0)) /*目的是分屏显示*/{printf("\n\npress any key to contiune...");getch();puts("\n\n");}printf_one(i); /*调用显示一个记录的函数*/printf("\n");}printf("\t there are %d record.\n",n);printf("\n pass any key to back...");getch(); /*按任意键*/menu();}⑷查找模块[需求分析]该模块的功能是根据输入的职工姓名和卡号查找对应的记录.[流程图]NY 121 2[程序]/***************查找函数***************/void search() /*查找模块*/ {int n,w1; do {puts("\t\t\t1.search by name"); puts("\t\t\t2.search by num"); scanf("%d",&n);if(n<1||n>2) /*对选择数字作判断*/ {w1=1; getchar(); }else w1=0; }while(w1==1); switch(n) {void search_1(); void search_2();case 1:search_1();break; case 2:search_2();break; }开 始输入n判断n 值按姓名查询按卡号查询输出返回? 浏览职工信息主菜单}void search_1() /*按姓名查找*/{int load();void printf_face();void menu();void printf_one(int i);int i,n,k,w1=1,w2,w3,w4;struct list s;n=load();do{do{k=-1;printf("\n\nenter name that you want to search! name:");scanf("%s",);printf_face(); /*调用显示数据结构项目函数*/for(i=0;i<n;i++) /*查找所需数据*/if(strcmp(,list[i].name)==0){k=i; /*找到数据*/printf_one(k);break; /*调用显示一个记录的函数*/}if(k==-1){printf("\n\n NO.exit!please");printf("\n\nare you again?\n\t1).again 2).NO and back [ ]\b\b");scanf("%d",&w1);if(w1==2)break;}}while(k==-1&&w1==1); /*如果w1不等于1这直接返回*/w4=0;w3=0;if(k!=-1) /*k不等于-1表示已找到,如果找到则选择操作*/{printf("successful");printf("\n\n what do you want to do?\n\t1).search another 2).back [ ]\b\b");scanf("%d",&w2);}}while(w2==1);}void search_2() /*按卡号查找*/{int load();void printf_face();void menu();void printf_one(int i);struct list s;int i,n,k,w1=1,w2,w3,w4;n=load();do{do{k=-1;printf("\n\nenter num that you want to search! num:");scanf("%d",&s.num);printf_face(); /*调用显示数据结构项目函数*/for(i=0;i<n;i++) /*查找所需数据*/if(s.num==list[i].num){k=i; /*找到数据*/printf_one(k);break; /*调用显示一个记录的函数*/}if(k==-1){printf("\n\n NO.exit!please");printf("\n\nare you again?\n\t1).again 2).NO and back [ ]\b\b");scanf("%d",&w1);if(w1==2)break;}}while(k==-1&&w1==1); /*如果w1不等于1这直接返回*/w4=0;w3=0;if(k!=-1) /*k不等于-1表示已找到,如果找到则选择操作*/{printf("\nsuccessful");printf("\n\n what do you want to do?\n\t1).search another 2).back [ ]\b\b");scanf("%d",&w2);}while(w2==1); menu();}⑸ 排序模块[需求分析]该模块的功能是将职工记录按照一定顺序排序. [流程图]NY1212/***************排序模块***************/ void order() /*排序模块*/ {int w1,n;void order_1(); void order_2(); do {puts("\t\t\t1.order by num"); puts("\t\t\t2.order by salary"); scanf("%d",&n);if(n<1||n>2) /*对选择数字作判断*/开 始输入n判断n 是否是0到2按工资卡号排序按实发工资排序输出返回?浏览职工信息主菜单{w1=1;getchar();}else w1=0;}while(w1==1);switch(n){case 1:order_1();break;case 2:order_2();break;}}void order_1() /*卡号升序排*/{int load();void printf_back();void save(int i);int i,j,n,k;void browse();struct list s;n=load();for(i=0;i<n-1;i++) /*选择法排序*/{k=i;for(j=i+1;j<n;j++)if(list[j].num<list[k].num)k=j;s=list[i];list[i]=list[k];list[k]=s;}save(n);browse();puts("\n\n");printf_back();}void order_2() /*工资降序排*/{int load();void printf_back();void save(int i);int i,j,n,k;struct list s;n=load();for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++) /*选择法排序*/if(list[k].salary2<list[j].salary2)k=j;s=list[i];list[i]=list[k];list[k]=s;}save(n);browse();puts("\n\n");printf_back();}六、程序代码(每个函数都要有功能说明)#include<stdio.h>#include<string.h>#include<conio.h>#include<stdlib.h>#define N 50void main(){void menu();menu();}void menu() //主菜单函数{void enter();void add();void browse();void search();void order();int n,w1;do{puts("\t\t*********************MENU*************************\n\n");puts("\t\t\t 1.Enter ");puts("\t\t\t 2.Add");puts("\t\t\t 3.browse all");puts("\t\t\t 4.Search ");puts("\t\t\t 5.Order ");puts("\t\t\t 6.Exit");puts("\n\n\t\t*************************************************\n");printf("Choice your number(1-6):[]\b\b");scanf("%d",&n);if(n<1||n>6) /*对选择的数字进行判断*/{w1=1;getchar();}else w1=0;}while(w1==1);switch(n){case 1:enter();break; /*输入模块*/case 2:add();break; /*新增模块*/case 3:browse();break; /*浏览模块*/case 4:search();break; /*查找模块*/case 5:order();break; /*排序模块*/case 6:exit(0); /*退出模块*/}}struct list //结构体定义工资信息{int num; //工资卡号char name[20]; //姓名int month; //月份int salary1; //应发工资int water; //水费int electrisity; //电费float fax; //税金float salary2; //实发工资}list[N]; //list[N]中每个数组元素对应一个职工工资信息void enter() //输入模块函数{void printf_back();void save(int n);void input(int i);int i,n;printf("how many workers (1-%d)?:",N-1);scanf("%d",&n); //输入职工数目printf("\n enter date now\n\n");for(i=0;i<n;i++) //输入职工各项信息{printf("\n input %dth student record.\n",i+1);input(i); //调用职工信息输入函数}if(i!=0)save(n); //储存职工信息printf_back(); //执行返回函数}void add() //新增模块函数{void printf_back();int i,n,m,k;int load();void save(int n);void input(int i);FILE *fp; //定义文件指针变量n=load(); //导出文件信息,得到返回值printf("how many workers are you want to add(0-%d)?:",N-1-n);scanf("%d",&m); //输入新增职工数目k=m+n; //总职工数= 新增职工数+已有职工数for(i=n+1;i<=k;i++) //输入新增职工信息{printf("\n input %dth workers record.\n",i-n+2);input(i); //调用职工信息输入函数}fp=fopen("workers.txt","ab"); //以追加形式打开文件for(i=n+1;i<=k;i++)fwrite(&list[i],sizeof(struct list),1,fp); //将内存中的职工信息输出到磁盘文件中save(n); //储存输入信息fclose(fp); //关闭文件printf_back(); //执行返回函数}void browse() //浏览模块函数{void printf_one(int i);void printf_face();int load();void menu();int i,n;n=load();printf_face();for(i=0;i<n;i++){if((i!=0)&&(i%10==0)) //以10个职工为一组输出{printf("\n\npass any key to continue...");getch();puts("\n\n");}printf_one(i); //输出各职工信息printf("\n");}printf("\t there are %d recode.\n",n);printf("\n pass any key to back..");getch();menu(); //返回主菜单}void search() //查询模块函数{int n,w1;do{puts("\t\t\t1.search by name"); //按姓名查询puts("\t\t\t2.search by num"); //按工资卡号查询scanf("%d",&n);if(n<1||n>2){w1=1;getchar();}else w1=0;}while(w1==1);switch(n){void search_1();void search_2();case 1:search_1();break;case 2:search_2();break;}}void search_1() //按姓名查询{int load();void printf_face();void menu();void printf_one(int i);int i,n,k,w1=1,w2,w3,w4;struct list s;n=load(); //导出文件信息,得到返回值do{do{k=-1;printf("\n\nenter name that you want to search! name:");scanf("%s",); //输入要查找的姓名printf_face(); //输出职工信息项目for(i=0;i<n;i++)if(strcmp(,list[i].name)==0) //查询出与输入姓名相同的职工的信息{k=i;printf_one(k);break;//输出查询结果并中断,说明只能输出查到的第一个数据}if(k==-1) //如果没有查出信息则执行如下选择菜单{printf("\n\n NO.exit!please");printf("\n\nare you again?\n\t1).again 2).NO and back []\b\b");scanf("%d",&w1);if(w1==2)break;}}while(k==-1&&w1==1); //选择1继续循环执行查询w4=0;w3=0;if(k!=-1){printf("successful");printf("\n\n what do you want to do?\n\t1).search another 2).back []\b\b"); //选择查找下一个数据或返回scanf("%d",&w2);}}while(w2==1); //选择1循环执行查询下一个数据menu();}void search_2() //按工资卡号查询int load();void printf_face();void menu();void printf_one(int i);struct list s;int i,n,k,w1=1,w2,w3,w4;n=load();do{do{k=-1;printf("\n\nenter num that you want to search! num:");scanf("%d",&s.num); //输入要查找的工资卡号printf_face(); //输出职工信息项目for(i=0;i<n;i++)if(s.num==list[i].num) //查询出与输入工资卡号相同的职工的信息{k=i;printf_one(k);break;}if(k==-1) //如果没有查出信息则执行如下选择菜单{printf("\n\n NO.exit!please");printf("\n\nare you again?\n\t1).again 2).NO and back []\b\b");scanf("%d",&w1);if(w1==2)break;}}while(k==-1&&w1==1); //选择1继续循环执行查询w4=0;w3=0;if(k!=-1){printf("successful");printf("\n\n what do you want to do?\n\t1).search another 2).back []\b\b");scanf("%d",&w2);}}while(w2==1); //选择1循环执行查询下一个数据menu();void order() //排序功能模块函数{ int w1,n;void order_1();void order_2();do{puts("\t\t\t1.order by num"); //按工资卡号排序puts("\t\t\t2.order by salary 2"); //按实发工资排序scanf("%d",&n);if(n<1||n>2){w1=1;getchar();}else w1=0;}while(w1==1);switch(n){case 1:order_1();break;case 2:order_2();break;}}void order_1() //按工资卡号升序排序{int load();void printf_back();void save(int i);int i,j,n;void browse();struct list s;n=load();for(i=0;i<n-1;i++) //冒泡排序法,按职工工资卡号升序排列出职工信息{for(j=i+1;j<n-1;j++){if(list[j].num<list[i].num)s=list[j];list[j]=list[i];list[i]=s;}}save(n); //储存排序后的信息browse(); //显示排序后的信息puts("\n\n");printf_back(); //执行返回函数}void order_2() //按实发工资升序排序{int load();void printf_back();void save(int i);int i,j,n;struct list s;void browse();n=load();for(i=0;i<n-1;i++) //冒泡排序法,按实发工资升序排列出职工信息{for(j=i+1;j<n-1;j++){if(list[i].salary2<list[j].salary2)s=list[j];list[j]=list[i];list[i]=s;}}save(n); //储存排序后的信息browse(); //显示排序后的信息puts("\n\n");printf_back(); //执行返回函数}void save(int n) //储存函数{FILE *fp;int i;fp=fopen("workers.txt","wb"); //以只写方式打开文件for(i=0;i<n;i++)fwrite(&list[i],sizeof(struct list),1,fp); //将内存中的职工信息输出到磁盘文件中fclose(fp); //关闭文件}int load() //导出文件信息{int i;fp=fopen("workers.txt","rb"); //以只读方式打开文件for(i=0;!feof(fp);i++)fread(&list[i],sizeof(struct list),1,fp); //读出磁盘文件中的职工信息fclose(fp); //关闭文件return(i-1); //返回数值i-1}void input(int i) //职工信息输入函数{float salary2(int i);float fax(int i);printf("No.:");scanf("%d",&list[i].num);printf("name:");scanf("%s",list[i].name);printf("month:");scanf("%d",&list[i].month);printf("salary1:");scanf("%d",&list[i].salary1);printf("water:");scanf("%d",&list[i].water);printf("electricity:");scanf("%d",&list[i].electrisity);fax(i); //计算税金salary2(i); //计算实发工资}float fax(int i) //税金计算函数{if(list[i].salary1<800)list[i].fax=0;else if(list[i].salary1<1400)list[i].fax=(((list[i].salary1-800)*5/100));else list[i].fax=(((list[i].salary1-1400)/10));return list[i].fax;}float salary2(int i) //实发工资计算函数{list[i].salary2=(list[i].salary1-list[i].water-list[i].electrisity-list[i].fax);return list[i].salary2;}void printf_back() //返回函数{int w;void menu();void browse();printf("\n\n\tsuccessful!");printf("what do you want to do?\n\n\t1).browse all now\t2).back: []\b\b"); //菜单选择浏览职工信息或返回主菜单scanf("%d",&w);if(w==1)browse(); //输入1选择浏览职工信息else menu(); //输入2返回主菜单}void printf_one(int i) //单个职工信息输出函数{printf("%9d",list[i].num);printf("%9s",list[i].name);printf("%9d",list[i].month);printf("%9d",list[i].salary1);printf("%9d",list[i].water);printf("%9d",list[i].electrisity);printf("%9.2f",list[i].fax);printf("%9.2f",list[i].salary2);}void printf_face() //职工信息项目{printf("\n\tNo. name month salary1 water electrisity fax salary2\n");}七、程序运行结果1、主函数运行,显示主菜单函数menu()2、输入数字1,添入两组数据3、如果输入数字2,新增一组数据并浏览4、输入数字3,浏览所有职工信息5、输入4,进行查询程序,再输入1 ,按姓名查询,输入2 ,按工资卡号查询6、输入数字5,进行排序程序,输入1 ,按卡号排序,输入2按实发工资排序。