北 京 林 业 大 学
2020学年—2021学年第1学期 程序设计基础课程设计 实习报告书
实习内容: 高校教师工资管理系统
实习环境: Sublime Text 3
目录
一、实习步骤
二、实现方法概述
三、技术方案实现
3.0 数据存储结构
3.0.0本地存储结构(**创新点**)
3.0.1 教师信息结构体 及 学院职称映射数组
3.0.2 薪资信息结构体
3.0.3 学院平均值统计结构体 与 职称平均值统计结构体
3.1 Operation Functions 概述
3.2 Check Functions 概述
3.2.1 checkten()--对输入的数字范围进行检测
3.2.2 checkdb()--检测用户输入是否为实数
3.2.3 checkid()--检测用户输入id是否合法且合规
3.2.4 checkname()--检测用户名字是否存在
3.2.5 checkmon()--用以检测所要查询的月份是否存在salary信息中
3.3 Storage Functions 概述
3.3.1 inpter() inpsal()--ter输入函数 与 sal输入函数
3.3.2 delter() delsal()--删除教师信息及薪资信息
3.3.3 自定义简便SQL操作
3.4 Algorithm Functions 概述
3.4.1 showter()--可选mode的教师信息列表打印函数
3.4.2 searchterid() searchsalid()--寻找所传id对应的实际索引以便后续操作
3.4.3 swapter()swapsal()swapcol()swapjob()--交换函数
3.4.4 sortter_id() sortsal_id()--排序函数
3.4.5 calcolavg_sort() caljobavg_sort()--实现统计分析排序功能的函数
3.4.6 FreshSalName()--同步sal与ter之间的信息
四、结果展示:
4.0开始界面
4.1进入录入数据并保存功能
4.1.1教师信息录入功能
4.1.2录入教师工资信息
4.1.3 保存到本地功能
4.2 进入修改数据并保存功能
4.2.1 根据工号修改某位教师的基本信息和工资信息
4.2.2 根据姓名修改某位教师的基本信息和工资信息
4.2.3 删除某一工号的教师的所有信息
4.3查询显示功能
4.3.1展示所有教师的基本信息
4.3.2根据月份显示所有教师当月工资信息(以工号为序)
4.3.3根据工号查询某位教师某一月份的基本信息和工资信息
4.3.4根据姓名查询某位教师某一月份的基本信息和工资信息
4.4统计分析
4.4.1根据月份,统计不同学院教师的平均应发工资和平均实发工资
4.4.2根据月份,统计不同职称教师的平均应发工资和平均实发工资
4.5从本地导入数据(**创新点**)
4.6保存并退出功能
五、结束语:
一、实习步骤:
我于第一天进行该项目的整体分析及技术方案的选择,第二天进行该程序的编码工作,第三天进行程序的测试工作和报告的书写工作。
二、实现方法概述:
根据要求,该程序完全基于C语言实现,未使用任何外部库文件。代码全部手敲完成,无任何借鉴复制行为。且编写代码的全过程已录制视频,并将快放版上传至B站:其地址为:https://www.bilibili.com/video/BV1Af4y1e7Tc/
该程序按照实验要求分为五大模块,完全实现实验要求的所有功能。存储在程序内采用结构体的方式,由于禁止使用SQL库函数,所以我自己手写了一套简化版的SQL生成与解析函数,用于程序在本地的存储结构(可实现对之前数据,或样例数据的导入)。
设计采用自顶向下的方式,将每个大问题细化为各个小问题。将需要重复用到的解决方案算法生成为可选择模式的函数(如4.0.1 showter()),以达到简化代码量且提高可移植性的目标。每完成一个小模块便进行测试,以确保程序的正确性。
本系统系统功能结构
三、技术方案实现:
该程序的函数功能分为四大模块,接下来将一一介绍。
3.0 数据存储结构
3.0.0本地存储结构(**创新点**)
由于该项目禁止使用SQL数据库的相关库文件,我自己写了一套类似于SQL存储结构的生成函数及解释函数。其于本地存储的样式类似于SQL中的insert values()语句。
- (0000000001,wu zheng,3,2)
- (0000000003,qian,3,2)
- (0000000001,wu zheng,3,2,2,200.00,100.00,56.00,300.00,244.00)
- (0000000001,wu zheng,3,2,3,45.00,6.00,6.00,51.00,45.00)
接下来将首先介绍该简化SQL的生成方法
- void savetolocter()
- {
- // (id,name,colid,jobid)
- FILE * f1;
- f1=fopen("terdata.dat","w+");
- if(f1==NULL){printf("save to local unaviliable\n");return;}
- int i;
- for(i=0;i
- {
- char tline[101]="(", tnum[5];
- strcat(tline,ter[i].id);
- strcat(tline,",");
- strcat(tline,ter[i].name);
- strcat(tline,",");
- strcat(tline,itoa(ter[i].collegeid,tnum,10));
- strcat(tline,",");
- strcat(tline,itoa(ter[i].jobid,tnum,10));
- strcat(tline,")");
- fprintf(f1, "%s\n", tline);
- }
- fclose(f1);
- }
-
- void savetolocsal()
- {
- FILE * f1;
- f1=fopen("saldata.dat","w+");
- if(f1==NULL){printf("save to local unaviliable\n");return;}
- int i;
-
- for(i=0;i
- {
- char tline[201]="(", tnum[12];
- strcat(tline,sal[i].id);
- strcat(tline,",");
- strcat(tline,sal[i].name);
- strcat(tline,",");
- strcat(tline,itoa(sal[i].collegeid,tnum,10));
- strcat(tline,",");
- strcat(tline,itoa(sal[i].jobid,tnum,10));
- strcat(tline,",");
- strcat(tline,itoa(sal[i].month,tnum,10));
- strcat(tline,",");
- strcat(tline,d2s(sal[i].basicsal,tnum));
- strcat(tline,",");
- strcat(tline,d2s(sal[i].addsal,tnum));
- strcat(tline,",");
- strcat(tline,d2s(sal[i].subsal,tnum));
- strcat(tline,",");
- strcat(tline,d2s(sal[i].theosal,tnum));
- strcat(tline,",");
- strcat(tline,d2s(sal[i].truesal,tnum));
- strcat(tline,")");
- fprintf(f1, "%s\n", tline);
- }
- fclose(f1);
-
- }
其核心思想为模拟SQL的数据以逗号为分割的方式,将数据行通过fprintf结构化的存入到文件中,以便后续的读取。
接下来将介绍该SQL语句的解析函数
- void loadlocter(char * loc)
- {
- FILE * f1;
- f1=fopen(loc,"r");
- if(f1==NULL){printf("load to here unaviliable\n");return;}
-
- tercnt=0;
- char tinp[100];
- while(fgets(tinp,300,f1)!=NULL && tinp[0]!=10)
- {
- char tid[11],tna[31];
- int tcd,tjd;
- int i;
- for(i=1;i<=10;i++) tid[i-1]=tinp[i];
- int tcnt=0;
- for(i=12;tinp[i]!=',';i++) tna[tcnt++]=tinp[i];
- tna[tcnt]='\0';
- tcd=atoi(&tinp[i+1]);
- tjd=atoi(&tinp[i+3]);
-
- strcpy(ter[tercnt].id,tid);
- strcpy(ter[tercnt].name,tna);
- ter[tercnt].collegeid=tcd;
- ter[tercnt].jobid=tjd;
- tercnt++;
-
- //(1234567890,de d,1,1)
- }
- fclose(f1);
- sortter_id();
- }
-
-
- void loadlocsal(char * loc)
- {
- FILE * f1;
- f1=fopen(loc,"r");
- if(f1==NULL){printf("load to here unaviliable\n");return;}
-
- salcnt=0;
- char tinp[200];
- while(fgets(tinp,300,f1)!=NULL && tinp[0]!=10)
- {
- char tid[11],tna[31];
- int tcd,tjd;
- double t1,t2,t3,t4,t5;
-
- int i;
- for(i=1;i<=10;i++) tid[i-1]=tinp[i];
- int tcnt=0;
- for(i=12;tinp[i]!=',';i++) tna[tcnt++]=tinp[i];
- tna[tcnt]='\0';
- tcd=atoi(&tinp[++i]);i++;
- tjd=atoi(&tinp[++i]);i+=2;
- char tmon[4];tcnt=0;
- for(;tinp[i]!=',';i++) tmon[tcnt++]=tinp[i];
- tmon[tcnt]='\0';
- int mon=atoi(tmon);
- char tc[15];tcnt=0;
-
- for(i++;tinp[i]!=',';i++) tc[tcnt++]=tinp[i];
- tc[tcnt]='\0';t1=atof(tc);tcnt=0;
- for(i++;tinp[i]!=',';i++) tc[tcnt++]=tinp[i];
- tc[tcnt]='\0';t2=atof(tc);tcnt=0;
- for(i++;tinp[i]!=',';i++) tc[tcnt++]=tinp[i];
- tc[tcnt]='\0';t3=atof(tc);tcnt=0;
- for(i++;tinp[i]!=',';i++) tc[tcnt++]=tinp[i];
- tc[tcnt]='\0';t4=atof(tc);tcnt=0;
- for(i++;tinp[i]!=')';i++) tc[tcnt++]=tinp[i];
- tc[tcnt]='\0';t5=atof(tc);tcnt=0;
-
- strcpy(sal[salcnt].id,tid);
- strcpy(sal[salcnt].name,tna);
- sal[salcnt].collegeid=tcd;
- sal[salcnt].jobid=tjd;
- sal[salcnt].month=mon;
- sal[salcnt].basicsal=t1;
- sal[salcnt].addsal=t2;
- sal[salcnt].subsal=t3;
- sal[salcnt].theosal=t4;
- sal[salcnt].truesal=t5;
-
- salcnt++;
-
- }
- fclose(f1);
-
- }
其核心为检测逗号所在位置,并以逗号为分割符,进行数据类型的转换操作,最后复制到相应的变量中。
3.0.1 教师信息结构体 及 学院职称映射数组
- struct Teacher{
- char id[11];
- char name[31];
- int collegeid;
- int jobid;
- }ter[NTer],tmpt; // use tmp to change
- int tercnt=0; // count the number of all teacher
- char col_sec[Ncol+1][31]={ "","Information","Engineer","Theory","Arts","Biology"}; // college nubmer to name
- char job_sec[Njob+1][31]={ "","Professor","Ass-Professor","Teacher","Tutor"}; // job nubmer to name
该段特殊采用数字映射字符串的方法,将学院职称皆量化为int,方便后续的操作。
3.0.2 薪资信息结构体
- struct Salary{
- char id[11];
- char name[31];
- int collegeid;
- int jobid;
- int month;
- double basicsal, addsal, subsal, theosal, truesal;
- }sal[Nsal],tmps;
- int salcnt=0; // count the number of all records
basicsal—基本工资,addsal—业绩津贴,subsal—扣除费用,theosal—应发工资,truesal—实发工资。
3.0.3 学院平均值统计结构体 与 职称平均值统计结构体
- struct College
- {
- int collegeid;
- double thavg,travg;
- }col[6],tmpc;
-
- struct Job
- {
- int jobid;
- double thavg,travg;
- }job[6],tmpj;
进行统计分析时使用。
3.1 Operation Functions 概述
该部分代码实现了程序与外接交互的全部功能。负责读取用户的操作输入,并与用户进行交互。 该部分具体内容将在【四】中进行演示并介绍。
3.2 Check Functions 概述
该部分代码对实现程序鲁棒性检测及排除起到了重要作用,下面将依次介绍其实现方案。
3.2.1 checkten()--对输入的数字范围进行检测
(应用于用户菜单选择等)
- int checkten(int L,int R)
- {
- char opeinp[20];
-
- scanf("%s",opeinp);
- while ((atoi(opeinp)) == 0 or (atoi(opeinp)) > R or (atoi(opeinp)) < L )
- {
- printf("your input is invalid,please input again(just number from %d to %d):____\b\b\b",L,R);
- scanf("%s",opeinp);
- }
- return atoi(opeinp);
- }
通过atoi函数实现输入字符串向int类型的转换工作,并判断其大小范围是否在给定的[L,R]区间内,如果非数字,或非所需区间,则给出提示并反复要求用户输入,直至用户输入合法,返回该数值。
3.2.2 checkdb()--检测用户输入是否为实数
(用于工资输入的鲁棒性检查)
- double checkdb()
- {
- char opeinp[20];
-
- scanf("%s",opeinp);
- while ((atof(opeinp)) == 0)
- {
- printf("your input is invalid,please input again(just a real number):________\b\b\b\b\b\b\b\b");
- scanf("%s",opeinp);
- }
- return atof(opeinp);
- }
通过atof函数,将输入字符串转换为double类型,如若转换失败(atof返回值为0),则给出提示并反复要求用户输入,直至用户输入合法,返回该数值。
3.2.3 checkid()--检测用户输入id是否合法且合规
(用于id输入的鲁棒性检查)
- void checkid(char * inpid, int judgeexist)
- { // if judgeexist == 1 , until input exist then return;
- // if judgeexist == 2 , until input not exist return;
- while(scanf("%s",inpid))
- {
- if(inpid[10] != '\0')
- { // check 10 digit to stop
- printf("your ID format is invalid,please make sure it is consist of 10 nubmers,ID:__________\b\b\b\b\b\b\b\b\b\b");
- continue;
- }
-
- int i;
- for(i = 0; i < 10; i++)
- {
- if(inpid[i] > '9' or inpid[0] < '0')
- {
- printf("your ID format is invalid,please make sure it is consist of 10 nubmers,ID:__________\b\b\b\b\b\b\b\b\b\b");
- break;
- }
- }
-
- if(i==10)
- { // format valid
- // to check existence
- int f=0; // 0 not exist; 1 exist
-
- for(i = 0;i < tercnt; i++)
- {
- if(strcmp(ter[i].id, inpid) == 0)
- {
- f=1;
- //printf("your ID input is existed, please make sure it's new one's id,ID:__________\b\b\b\b\b\b\b\b\b\b");
- break;
- }
- }
- if(judgeexist==1)
- {
- if(f==0)
- {
- printf("your ID input is not existed, please make sure it's above one's id,ID:__________\b\b\b\b\b\b\b\b\b\b");
- continue;
- }
- if(f==1)
- {
- return ;
- }
- }
- if(judgeexist==2)
- {
- if(f==1)
- {
- printf("your ID input is existed, please make sure it's new one's id,ID:__________\b\b\b\b\b\b\b\b\b\b");
- continue;
- }
- if(f==0)
- {
- return ;
- }
- }
- }
- }
- return ; // no use,just done for warning
- }
该函数6-10行判断输入是否为10位,10位判断合法后,进入每位是否为数字的判断,再次合法后,才将进入可选mode的判断。
该函数我设置为可选mode,如果judgeexist == 1 ,则直到所输入id存在于系统中才会返回,如果judgeexist == 1 ,则直到所输入id是不事先存在的才会返回。该实现有利于后续的实际操作
3.2.4 checkname()--检测用户名字是否存在
(用于检索名字时的鲁棒性检测)
- int checkname(char * inpname)
- {
- int t=0;
- rewind(stdin);
- while(1)
- {
- gets(inpname);
-
- rewind(stdin);
- int i;
- for(i=0;i
- {
- if(strcmp(ter[i].name,inpname) == 0)
- {
- return 1;
- }
- }
- printf("your name input is not existed, please make sure it's above one's name,NAME:__________\b\b\b\b\b\b\b\b\b\b");
- t++;
- if(t==5) break;
- }
- return 0;
- }
-
该函数将遍历整个ter结构体内的所有name,直至有匹配才返回,如若一直未匹配,则证明不存在该名字,故提示用户重新输入。
3.2.5 checkmon()--用以检测所要查询的月份是否存在salary信息中
- int checkmon(int * mon,char * id)
- {
- int t=1; // tried too many times
- while(1)
- {
- t++;
- if(searchsalid(id,*mon)!=-1) return 1;
-
- printf("%d month do not have salary information\n",*mon);
- printf("please resure and then INPUT:_____\b\b\b");
-
- *mon=checkten(1,12);
- if(t==5) break;
- }
- return 0;
- }
通过调用searchsalid 并进行匹配实现(后续将介绍该函数)
3.3 Storage Functions 概述
这些函数实现了数据的录入,修改,删除,以及本地化SQL存储等功能。
接下来将一一介绍。
3.3.1 inpter() inpsal()--ter输入函数 与 sal输入函数
- void inpter(int tid,int notfirst)
- {
- printf("Input the Teacher's NAME:______________\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
- rewind(stdin);
- gets(ter[tid].name); // to ignored the sperate by space
- printf("Input the college index of the teacher:\n1.Information,2.Engineer,3.Theory,4.Art,5.Biology. INPUT:___\b\b");
- ter[tid].collegeid=checkten(1,5);
- printf("Input the job index of the teacher:\n1.Professor,2.Ass-Professor,3.Teacher,4.Tutor. INPUT:___\b\b");
- ter[tid].jobid=checkten(1,4);
-
- struct Salary * sa;
- for(sa=sal;sa
- {
- if(strcmp(sa->id,ter[tid].id)==0)
- {
- strcpy(sa->name,ter[tid].name);
- sa->jobid = ter[tid].jobid;
- sa->collegeid = ter[tid].collegeid;
- }
- }
- if(notfirst == 0) tercnt++;
- showter(3,ter[tid].id);
- if(notfirst == 0) tercnt--;
- printf("BELOW INFORMATION SAVED SUCCESSFULly \n");
- printf("PRESS ENTER TO CONTINUE.\n");getchar();getchar();
- }
-
- void inpsal(int sid,int notfirst)
- {
- printf("please input the month(nubmer from 1 to 12):______\b\b\b");
- sal[sid].month=checkten(1,12);
- printf("please input the basic salary:________\b\b\b\b\b\b\b\b");
- sal[sid].basicsal=checkdb();
- printf("please input the additional salary:________\b\b\b\b\b\b\b\b");
- sal[sid].addsal=checkdb();
- printf("please input the subtract salary:________\b\b\b\b\b\b\b\b");
- sal[sid].subsal=checkdb();
-
- sal[sid].theosal=sal[sid].basicsal+sal[sid].addsal;
- sal[sid].truesal=sal[sid].theosal-sal[sid].subsal;
- FreshSalName(sid);
- if(notfirst == 0) salcnt++;
- showsal(3,sal[sid].id,sal[sid].month);
- if(notfirst == 0) salcnt--;
- printf("BELOW INFORMATION SAVED SUCCESSFULlY \n");
- printf("PRESS ENTER TO CONTINUE.\n");getchar();getchar();
- }
该段代码实现了排除鲁棒性的输入功能,并将教师信息中的姓名,学院,职称等,(如果工资信息存在)更新给工资信息,且在输入完成后,显示最新信息,以便查验。
3.3.2 delter() delsal()--删除教师信息及薪资信息
- void deleteter(char * id)
- {
- // through swap and cnt-- to complete the delete operation
- swapter(&ter[tercnt-1],&ter[searchterid(id)]);
- tercnt--;
- }
- void deletesal(char * id)
- {
- int i;
- for(i=0;i
- {
- if(strcmp(sal[i].id,id) == 0)
- {
- swapsal(&sal[i],&sal[salcnt-1]);
- salcnt--;
- }
- FreshSalName(i); // to check bug
- }
- }
该删除方法为:交换当前元素和最后一位元素的全部信息(通过自定swap实现,后续将进行介绍),并将总元素个数的统计变量减一,以此实现该删除操作。
3.3.3 自定义简便SQL操作
已在3.0.0中介绍完毕,此处不再赘述。
3.4 Algorithm Functions 概述
该部分实现该程序的主要算法功能,接下来将一一介绍各函数的实现方法。
3.4.1 showter()--可选mode的教师信息列表打印函数
- int showter(int mode,char * cc)
- { // mode == 1: show all information
- // mode == 2: show NAME(tc)'s infromation
- // mode == 3: show ID(tc)'s information
- int re=-1;
- struct Teacher * tc;
- printf("\n---------------------------Basic Information---------------------\n");
- printf("|ID\t\t|NAME\t\t|COLLEGE\t|JOB\t\t|\n");
- printf("-----------------------------------------------------------------\n");
- for(tc=ter;tc
- {
- if(mode == 1) printf("|%s\t|%-15s|%-15s|%-15s|\n",tc->id,tc->name,col_sec[tc->collegeid],job_sec[tc->jobid]);
- if(mode == 2 && (strcmp(tc->name,cc) == 0) ) printf("|%s\t|%-15s|%-15s|%-15s|\n",tc->id,tc->name,col_sec[tc->collegeid],job_sec[tc->jobid]);
- if(mode == 3 && (strcmp(tc->id,cc) == 0) )
- {
- re=tc-ter; // return his cntid
- printf("|%s\t|%-15s|%-15s|%-15s|\n",tc->id,tc->name,col_sec[tc->collegeid],job_sec[tc->jobid]);
- }
- }
- printf("-----------------------------------------------------------------\n\n");
- return re;
- }
-
-
- void showsal(int mode,char * cc,int mon)
- { // mode == 1: show all information
- // mode == 2: show NAME(tc)'s infromation
- // mode == 3: show ID(tc)'s information
- // if mon == 0 then cout every information
- // if mon == 1~12 then just cout the month's information
- struct Salary * sa;
- printf("\n-------------------------------------------------Salary Information------------------------------------------------------\n");
- printf("|Month\t|ID\t\t|NAME\t\t|Basic($)\t|Allowance($)\t|Subtract($)\t|Theory($)\t|True($)\t|\n");
- printf("-------------------------------------------------------------------------------------------------------------------------\n");
- for(sa=sal;sa
- {
- if(mode == 1 && (mon==0?1:sa->month==mon)) printf("|%d\t|%-15s|%-15s|%-15.2f|%-15.2f|%-15.2f|%-15.2f|%-15.2f|\n",sa->month,sa->id,
- sa->name,sa->basicsal,sa->addsal,sa->subsal,sa->theosal,sa->truesal);
- if(mode == 2 && (strcmp(sa->name,cc) == 0) && (mon==0?1:(sa->month==mon))) printf("|%d\t|%-15s|%-15s|%-15.2f|%-15.2f|%-15.2f|%-15.2f|%-15.2f|\n",sa->month,sa->id,
- sa->name,sa->basicsal,sa->addsal,sa->subsal,sa->theosal,sa->truesal);
- if(mode == 3 && (strcmp(sa->id,cc) == 0) && (mon==0?1:(sa->month==mon))) printf("|%d\t|%-15s|%-15s|%-15.2f|%-15.2f|%-15.2f|%-15.2f|%-15.2f|\n",sa->month,sa->id,
- sa->name,sa->basicsal,sa->addsal,sa->subsal,sa->theosal,sa->truesal);
- }
- printf("-------------------------------------------------------------------------------------------------------------------------\n\n");
- }
当mode为1时,将展示所有教师的基本信息或薪水信息;当mode为2时,将展示姓名为所传入参数的教师的基本信息或薪水信息;当mode为3时,将展示ID为所传入参数的教师基本信息或薪水信息。
并且该函数利用了printf的格式化输出功能,保证列表的整齐与美观。
3.4.2 searchterid() searchsalid()--寻找所传id对应的实际索引以便后续操作
- int searchterid(char * id)
- {
- int i;
- for(i=0; i < tercnt;i++)
- {
- if(strcmp(ter[i].id,id)== 0) return i;
- }
- return -1;
- }
-
- int searchsalid(char * id,int month)
- {
- int i;
- for(i=0;i
- {
- if(strcmp(id,sal[i].id)==0 && sal[i].month == month) return i;
- }
- return -1;
- }
额外地,在考虑查询月份需求的情况下,特假设month参数,以选择特定的month进行输出(给定 month和id时才能唯一的确定一条记录)。
3.4.3 swapter()swapsal()swapcol()swapjob()--交换函数
全部内容交换函数,通过临时变量交换法实现,此处不做赘述。
3.4.4 sortter_id() sortsal_id()--排序函数
以id为序,对ter和sal的排序函数
- void sortter_id()
- { // make the ter list sorted by the id
- int i,j;
- for(i=0;i
- for(j=tercnt-1;j>i;j--)
- if(strcmp(ter[j].id,ter[j-1].id)<0)
- swapter(&ter[j],&ter[j-1]);
- }
-
- void sortsal_id()
- { // make the sal list sorted by the 1:id 2:month
- int i,j;
- for(i=0;i
- for(j=salcnt-1;j>i;j--)
- {
- if(strcmp(sal[j].id,sal[j-1].id)<0)
- swapsal(&sal[j],&sal[j-1]);
- if(strcmp(sal[j].id,sal[j-1].id) == 0)
- if(sal[j].month < sal[j-1].month)
- swapsal(&sal[j],&sal[j-1]);
- }
- }
由于禁止使用C++的algorithm库及其sort函数,以及bool cmp() 排序规则,在此处我通过手写的方式,实现了相应的功能。基于冒泡排序和前面的swap函数实现。
3.4.5 calcolavg_sort() caljobavg_sort()--实现统计分析排序功能的函数
- void calcolavg_sort(int mon)
- {
- int i,j;
- for(i=1;i<=Ncol;i++)
- {
- double thsum=0,trsum=0,cnt=0; // th->theory tr->true
-
- for(j=0;j
- {
- if(sal[j].collegeid == i && sal[j].month == mon)
- {
- thsum += sal[j].theosal;
- trsum += sal[j].truesal;
- cnt++;
- }
- }
- col[i].collegeid = i;
- col[i].thavg= thsum?thsum/cnt:0;
- col[i].travg= trsum?trsum/cnt:0;
- }
-
- for(i=1;i<=Ncol;i++)
- for(j=Ncol;j>i;j--)
- {
- if(col[j].travg > col[j-1].travg)
- swapcol(&col[j],&col[j-1]);
- if(col[j].travg == col[j-1].travg)
- if(sal[j].collegeid < sal[j-1].collegeid)
- swapcol(&col[j],&col[j-1]);
- }
- }
-
- void caljobavg_sort(int mon)
- {
- int i,j;
- for(i=1;i<=Njob;i++)
- {
- double thsum=0,trsum=0,cnt=0; // th->theory tr->true
-
- for(j=0;j
- {
- if(sal[j].jobid == i && sal[j].month == mon)
- {
- thsum += sal[j].theosal;
- trsum += sal[j].truesal;
- cnt++;
- }
- }
- job[i].jobid = i;
- job[i].thavg= thsum?thsum/cnt:0;
- job[i].travg= trsum?trsum/cnt:0;
- }
-
- for(i=1;i<=Njob;i++)
- for(j=Njob;j>i;j--)
- {
- if(job[j].thavg > job[j-1].thavg)
- swapjob(&job[j],&job[j-1]);
- if(job[j].travg == job[j-1].travg)
- if(sal[j].jobid < sal[j-1].jobid)
- swapjob(&job[j],&job[j-1]);
- }
- }
该段程序通过对所选职业或学院的相应工资信息进行累加,并存储在job和college两个结构体中,最后对这两个结构体进行排序实现以上功能。
3.4.6 FreshSalName()--同步sal与ter之间的信息
由于涉及到对salary信息与teacher信息的同步更新,设定此函数
- void FreshSalName(int salind)
- {
- int i;
- for(i=0; i
- {
-
- if(strcmp(ter[i].id,sal[salind].id) == 0)
- {
- strcpy(sal[salind].name,ter[i].name);
-
- sal[salind].collegeid=ter[i].collegeid;
- sal[salind].jobid=ter[i].jobid;
- break;
- }
-
- }
- }
通过比对id后,进行赋值,实现相应功能。
四、结果展示:
4.0开始界面
展示软件信息及版本信息
进行321的倒计数后,进入程序的主界面
进入操作主菜单
鲁棒性测试(只有输入给定的操作数才可继续)
4.1进入录入数据并保存功能
4.1.1教师信息录入功能
(录入学号姓名等,并以代号形式录入学院,职称信息)
最终将该信息以列表的形式打印出来
鲁棒性测试4.1.1.1(教师id重复)
鲁棒性测试4.1.1.2(教师id出现特殊字符,id过长,id过短)
鲁棒性测试4.1.1.3(学院、职称出现特殊字符,过长,过短)
4.1.2录入教师工资信息
按照提示录入相应信息后,将会输出该调工资信息(人性化交互)
4.1.2.1 鲁棒性测试(输入不存在的id)
4.1.2.2 鲁棒性测试(输入不合法的月份信息)
4.1.2.3鲁棒性测试(输入不合法的钱数信息)
4.1.3 保存到本地功能
已成功存储到结构体和本地的dat文件中。
4.2 进入修改数据并保存功能
4.2.1 根据工号修改某位教师的基本信息和工资信息
修改基础信息:
修改工资信息:
4.2.1.1鲁棒性测试(当月份信息不存在时)
4.2.1.2鲁棒性测试(当多次输入错误月份信息时)--跳出避免死循环
其他鲁棒性继承于前序操作,此处不再重复演示。
4.2.2 根据姓名修改某位教师的基本信息和工资信息
Case1:该姓名不重复
Case2:该姓名存在重复情况 – 选择所需要选择的id输出即可
4.2.2.1鲁棒性测试(所输入的名字不存在) -- 提示重新输入
4.2.3 删除某一工号的教师的所有信息
将所有信息列出后,要求输入所要删除人的id
经过多次确认后方可删除,删除后输出最新的全部信息表格
4.3查询显示功能
4.3.1展示所有教师的基本信息
4.3.2根据月份显示所有教师当月工资信息(以工号为序)
4.3.3根据工号查询某位教师某一月份的基本信息和工资信息
4.3.4根据姓名查询某位教师某一月份的基本信息和工资信息
Case1:无重复时
Case2:有重复时
4.3.4.1鲁棒性测试(姓名不存在)
4.4统计分析
4.4.1根据月份,统计不同学院教师的平均应发工资和平均实发工资
4.4.2根据月份,统计不同职称教师的平均应发工资和平均实发工资
4.5从本地导入数据(**创新点**)
可选从上次存储数据中导入,或从演示样例数据中进行导入
导入成功后,将显示所导入的信息
4.6保存并退出功能
经过多次确认后方可退出
退出感谢信息
五、结束语:
以上为该程序的全部实现方法及演示,代码已传至个人GitHub上,该项目地址为:https://github.com/ShuoCHN/SalaryManageSystem。如有任何疑问或发现存在bug,请加私信与我进行讨论,谢谢!