北京林业大学《高校教师工资管理系统》课程设计

                                   北 京 林 业 大 学

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()语句。

  1. (0000000001,wu zheng,3,2)  
  2. (0000000003,qian,3,2)  
  3. (0000000001,wu zheng,3,2,2,200.00,100.00,56.00,300.00,244.00)
  4. (0000000001,wu zheng,3,2,3,45.00,6.00,6.00,51.00,45.00) 

接下来将首先介绍该简化SQL的生成方法

  1. void savetolocter()  
  2. {  
  3.     // (id,name,colid,jobid)  
  4.     FILE * f1;  
  5.     f1=fopen("terdata.dat","w+");  
  6.     if(f1==NULL){printf("save to local unaviliable\n");return;}  
  7.     int i;  
  8.     for(i=0;i<tercnt;i++)  
  9.     {  
  10.         char tline[101]="(", tnum[5];  
  11.         strcat(tline,ter[i].id);  
  12.         strcat(tline,",");  
  13.         strcat(tline,ter[i].name);  
  14.         strcat(tline,",");  
  15.         strcat(tline,itoa(ter[i].collegeid,tnum,10));  
  16.         strcat(tline,",");  
  17.         strcat(tline,itoa(ter[i].jobid,tnum,10));  
  18.         strcat(tline,")");  
  19.         fprintf(f1, "%s\n", tline);  
  20.     }  
  21.     fclose(f1);  
  22. }  
  23.   
  24. void savetolocsal()  
  25. {  
  26.     FILE * f1;  
  27.     f1=fopen("saldata.dat","w+");  
  28.     if(f1==NULL){printf("save to local unaviliable\n");return;}  
  29.     int i;  
  30.   
  31.     for(i=0;i<salcnt;i++)  
  32.     {  
  33.         char tline[201]="(", tnum[12];  
  34.         strcat(tline,sal[i].id);  
  35.         strcat(tline,",");  
  36.         strcat(tline,sal[i].name);  
  37.         strcat(tline,",");  
  38.         strcat(tline,itoa(sal[i].collegeid,tnum,10));  
  39.         strcat(tline,",");  
  40.         strcat(tline,itoa(sal[i].jobid,tnum,10));  
  41.         strcat(tline,",");  
  42.         strcat(tline,itoa(sal[i].month,tnum,10));  
  43.         strcat(tline,",");  
  44.         strcat(tline,d2s(sal[i].basicsal,tnum));  
  45.         strcat(tline,",");  
  46.         strcat(tline,d2s(sal[i].addsal,tnum));  
  47.         strcat(tline,",");  
  48.         strcat(tline,d2s(sal[i].subsal,tnum));  
  49.         strcat(tline,",");  
  50.         strcat(tline,d2s(sal[i].theosal,tnum));  
  51.         strcat(tline,",");  
  52.         strcat(tline,d2s(sal[i].truesal,tnum));  
  53.         strcat(tline,")");  
  54.         fprintf(f1, "%s\n", tline);  
  55.     }  
  56.     fclose(f1);  
  57.   
  58. }  

其核心思想为模拟SQL的数据以逗号为分割的方式,将数据行通过fprintf结构化的存入到文件中,以便后续的读取。

 

接下来将介绍该SQL语句的解析函数

  1. void loadlocter(char * loc)  
  2. {  
  3.     FILE * f1;  
  4.     f1=fopen(loc,"r");  
  5.     if(f1==NULL){printf("load to here unaviliable\n");return;}  
  6.       
  7.     tercnt=0;  
  8.     char tinp[100];  
  9.     while(fgets(tinp,300,f1)!=NULL && tinp[0]!=10)  
  10.     {  
  11.         char tid[11],tna[31];  
  12.         int tcd,tjd;  
  13.         int i;  
  14.         for(i=1;i<=10;i++) tid[i-1]=tinp[i];  
  15.         int tcnt=0;  
  16.         for(i=12;tinp[i]!=',';i++) tna[tcnt++]=tinp[i];  
  17.         tna[tcnt]='\0';  
  18.         tcd=atoi(&tinp[i+1]);  
  19.         tjd=atoi(&tinp[i+3]);  
  20.   
  21.         strcpy(ter[tercnt].id,tid);  
  22.         strcpy(ter[tercnt].name,tna);  
  23.         ter[tercnt].collegeid=tcd;  
  24.         ter[tercnt].jobid=tjd;  
  25.         tercnt++;  
  26.   
  27.         //(1234567890,de d,1,1)  
  28.     }  
  29.     fclose(f1);  
  30.     sortter_id();  
  31. }  
  32.   
  33.   
  34. void loadlocsal(char * loc)  
  35. {  
  36.     FILE * f1;  
  37.     f1=fopen(loc,"r");  
  38.     if(f1==NULL){printf("load to here unaviliable\n");return;}  
  39.       
  40.     salcnt=0;  
  41.     char tinp[200];  
  42.     while(fgets(tinp,300,f1)!=NULL && tinp[0]!=10)  
  43.     {  
  44.         char tid[11],tna[31];  
  45.         int tcd,tjd;  
  46.         double t1,t2,t3,t4,t5;  
  47.   
  48.         int i;  
  49.         for(i=1;i<=10;i++) tid[i-1]=tinp[i];  
  50.         int tcnt=0;  
  51.         for(i=12;tinp[i]!=',';i++) tna[tcnt++]=tinp[i];  
  52.         tna[tcnt]='\0';  
  53.         tcd=atoi(&tinp[++i]);i++;  
  54.         tjd=atoi(&tinp[++i]);i+=2;  
  55.         char tmon[4];tcnt=0;  
  56.         for(;tinp[i]!=',';i++) tmon[tcnt++]=tinp[i];   
  57.             tmon[tcnt]='\0';  
  58.         int mon=atoi(tmon);  
  59.         char tc[15];tcnt=0;  
  60.   
  61.         for(i++;tinp[i]!=',';i++) tc[tcnt++]=tinp[i];   
  62.             tc[tcnt]='\0';t1=atof(tc);tcnt=0;  
  63.         for(i++;tinp[i]!=',';i++) tc[tcnt++]=tinp[i];   
  64.             tc[tcnt]='\0';t2=atof(tc);tcnt=0;  
  65.         for(i++;tinp[i]!=',';i++) tc[tcnt++]=tinp[i];   
  66.             tc[tcnt]='\0';t3=atof(tc);tcnt=0;  
  67.         for(i++;tinp[i]!=',';i++) tc[tcnt++]=tinp[i];   
  68.             tc[tcnt]='\0';t4=atof(tc);tcnt=0;  
  69.         for(i++;tinp[i]!=')';i++) tc[tcnt++]=tinp[i];   
  70.             tc[tcnt]='\0';t5=atof(tc);tcnt=0;  
  71.   
  72.         strcpy(sal[salcnt].id,tid);  
  73.         strcpy(sal[salcnt].name,tna);  
  74.         sal[salcnt].collegeid=tcd;  
  75.         sal[salcnt].jobid=tjd;  
  76.         sal[salcnt].month=mon;  
  77.         sal[salcnt].basicsal=t1;  
  78.         sal[salcnt].addsal=t2;  
  79.         sal[salcnt].subsal=t3;  
  80.         sal[salcnt].theosal=t4;  
  81.         sal[salcnt].truesal=t5;  
  82.   
  83.         salcnt++;  
  84.   
  85.     }  
  86.     fclose(f1);  
  87.   
  88. }  

其核心为检测逗号所在位置,并以逗号为分割符,进行数据类型的转换操作,最后复制到相应的变量中。

 

3.0.1 教师信息结构体 及 学院职称映射数组

  1. struct Teacher{  
  2.     char id[11];  
  3.     char name[31];  
  4.     int collegeid; 
  5.     int jobid;  
  6. }ter[NTer],tmpt; // use tmp to change  
  7. int tercnt=0; // count the number of all teacher  
  8. char col_sec[Ncol+1][31]={ "","Information","Engineer","Theory","Arts","Biology"}; // college nubmer to name  
  9. char job_sec[Njob+1][31]={ "","Professor","Ass-Professor","Teacher","Tutor"}; // job nubmer to name  

该段特殊采用数字映射字符串的方法,将学院职称皆量化为int,方便后续的操作。

 

3.0.2 薪资信息结构体

  1. struct Salary{  
  2.     char id[11];  
  3.     char name[31];  
  4.     int collegeid;  
  5.     int jobid;  
  6.     int month;  
  7.     double basicsal, addsal, subsal, theosal, truesal;  
  8. }sal[Nsal],tmps;  
  9. int salcnt=0; // count the number of all records  

basicsal—基本工资,addsal—业绩津贴,subsal—扣除费用,theosal—应发工资,truesal—实发工资。

 

3.0.3 学院平均值统计结构体 与 职称平均值统计结构体

  1. struct College  
  2. {  
  3.     int collegeid;  
  4.     double thavg,travg;  
  5. }col[6],tmpc;  
  6.   
  7. struct Job  
  8. {  
  9.     int jobid;  
  10.     double thavg,travg;  
  11. }job[6],tmpj;  

进行统计分析时使用。

 

3.1 Operation Functions 概述

该部分代码实现了程序与外接交互的全部功能。负责读取用户的操作输入,并与用户进行交互。 该部分具体内容将在【四】中进行演示并介绍。

   

 

3.2 Check Functions 概述

该部分代码对实现程序鲁棒性检测及排除起到了重要作用,下面将依次介绍其实现方案。

3.2.1 checkten()--对输入的数字范围进行检测

                 (应用于用户菜单选择等)

  1. int checkten(int L,int R)  
  2. {  
  3.     char opeinp[20];  
  4.       
  5.     scanf("%s",opeinp);  
  6.     while ((atoi(opeinp)) == 0 or (atoi(opeinp)) > R or (atoi(opeinp)) < L )  
  7.     {  
  8.         printf("your input is invalid,please input again(just number from %d to %d):____\b\b\b",L,R);  
  9.         scanf("%s",opeinp);  
  10.     }  
  11.     return atoi(opeinp);  
  12. }  

通过atoi函数实现输入字符串向int类型的转换工作,并判断其大小范围是否在给定的[L,R]区间内,如果非数字,或非所需区间,则给出提示并反复要求用户输入,直至用户输入合法,返回该数值。

   

3.2.2 checkdb()--检测用户输入是否为实数

(用于工资输入的鲁棒性检查)

  1. double checkdb()  
  2. {  
  3.     char opeinp[20];  
  4.       
  5.     scanf("%s",opeinp);  
  6.     while ((atof(opeinp)) == 0)  
  7.     {  
  8.         printf("your input is invalid,please input again(just a real number):________\b\b\b\b\b\b\b\b");  
  9.         scanf("%s",opeinp);  
  10.     }  
  11.     return atof(opeinp);  
  12. }  

通过atof函数,将输入字符串转换为double类型,如若转换失败(atof返回值为0),则给出提示并反复要求用户输入,直至用户输入合法,返回该数值。

 

3.2.3 checkid()--检测用户输入id是否合法且合规

(用于id输入的鲁棒性检查)

  1. void checkid(char * inpid, int judgeexist)   
  2. { // if judgeexist == 1 , until input exist then return;  
  3.  // if judgeexist == 2 , until input not exist return;  
  4.     while(scanf("%s",inpid))  
  5.     {  
  6.         if(inpid[10] != '\0')  
  7.         { // check 10 digit to stop  
  8.             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");  
  9.             continue;  
  10.         }  
  11.   
  12.         int i;  
  13.         for(i = 0; i < 10; i++)  
  14.         {  
  15.             if(inpid[i] > '9' or inpid[0] < '0')  
  16.             {  
  17.                 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");  
  18.                 break;  
  19.             }  
  20.         }  
  21.   
  22.         if(i==10)  
  23.         {   // format valid  
  24.             // to check existence  
  25.             int f=0; // 0 not exist; 1 exist   
  26.               
  27.             for(i = 0;i < tercnt; i++)  
  28.             {  
  29.                 if(strcmp(ter[i].id, inpid) == 0)  
  30.                 {  
  31.                     f=1;  
  32.                     //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");  
  33.                     break;  
  34.                 }   
  35.             }  
  36.             if(judgeexist==1)  
  37.             {  
  38.                 if(f==0)  
  39.                 {  
  40.                     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");  
  41.                     continue;  
  42.                 }  
  43.                 if(f==1)  
  44.                 {  
  45.                     return ;  
  46.                 }  
  47.             }  
  48.             if(judgeexist==2)  
  49.             {  
  50.                 if(f==1)  
  51.                 {  
  52.                     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");  
  53.                     continue;  
  54.                 }  
  55.                 if(f==0)  
  56.                 {  
  57.                     return ;  
  58.                 }  
  59.             }  
  60.         }  
  61.     }  
  62.     return ; // no use,just done for warning  
  63. }  

该函数6-10行判断输入是否为10位,10位判断合法后,进入每位是否为数字的判断,再次合法后,才将进入可选mode的判断。

该函数我设置为可选mode,如果judgeexist == 1 ,则直到所输入id存在于系统中才会返回,如果judgeexist == 1 ,则直到所输入id是不事先存在的才会返回。该实现有利于后续的实际操作

 

3.2.4 checkname()--检测用户名字是否存在

(用于检索名字时的鲁棒性检测)

  1. int checkname(char * inpname)  
  2. {  
  3.     int t=0;  
  4.     rewind(stdin);  
  5.     while(1)  
  6.     {  
  7.         gets(inpname);  
  8.   
  9.         rewind(stdin);  
  10.         int i;  
  11.         for(i=0;i<tercnt;i++)  
  12.         {  
  13.             if(strcmp(ter[i].name,inpname) == 0)  
  14.             {  
  15.                 return 1;  
  16.             }  
  17.         }  
  18.         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");  
  19.         t++;  
  20.         if(t==5) break;  
  21.     }  
  22.     return 0;  
  23. }  
  24.  

该函数将遍历整个ter结构体内的所有name,直至有匹配才返回,如若一直未匹配,则证明不存在该名字,故提示用户重新输入。

 

3.2.5 checkmon()--用以检测所要查询的月份是否存在salary信息中

  1. int checkmon(int * mon,char * id)  
  2. {  
  3.     int t=1; // tried too many times  
  4.     while(1)  
  5.     {  
  6.         t++;  
  7.         if(searchsalid(id,*mon)!=-1) return 1;  
  8.   
  9.         printf("%d month do not have salary information\n",*mon);  
  10.         printf("please resure and then INPUT:_____\b\b\b");  
  11.   
  12.         *mon=checkten(1,12);  
  13.         if(t==5) break;  
  14.     }  
  15.     return 0;     
  16. }  

通过调用searchsalid 并进行匹配实现(后续将介绍该函数)

 

3.3 Storage Functions 概述

    这些函数实现了数据的录入,修改,删除,以及本地化SQL存储等功能。

    接下来将一一介绍。

 

3.3.1 inpter() inpsal()--ter输入函数 与 sal输入函数

  1. void inpter(int tid,int notfirst)  
  2. {  
  3.     printf("Input the Teacher's NAME:______________\b\b\b\b\b\b\b\b\b\b\b\b\b\b");  
  4.     rewind(stdin);  
  5.     gets(ter[tid].name); // to ignored the sperate by space  
  6.     printf("Input the college index of the teacher:\n1.Information,2.Engineer,3.Theory,4.Art,5.Biology. INPUT:___\b\b");  
  7.     ter[tid].collegeid=checkten(1,5);  
  8.     printf("Input the job index of the teacher:\n1.Professor,2.Ass-Professor,3.Teacher,4.Tutor. INPUT:___\b\b");  
  9.     ter[tid].jobid=checkten(1,4);  
  10.   
  11.     struct Salary * sa;  
  12.     for(sa=sal;sa<sal+salcnt;sa++)  
  13.     {  
  14.         if(strcmp(sa->id,ter[tid].id)==0)  
  15.         {  
  16.             strcpy(sa->name,ter[tid].name);  
  17.             sa->jobid = ter[tid].jobid;  
  18.             sa->collegeid = ter[tid].collegeid;  
  19.         }  
  20.     }  
  21.     if(notfirst == 0) tercnt++;  
  22.     showter(3,ter[tid].id);  
  23.     if(notfirst == 0) tercnt--;  
  24.     printf("BELOW INFORMATION SAVED SUCCESSFULly \n");  
  25.     printf("PRESS ENTER TO CONTINUE.\n");getchar();getchar();  
  26. }  
  27.   
  28. void inpsal(int sid,int notfirst)  
  29. {  
  30.     printf("please input the month(nubmer from 1 to 12):______\b\b\b");  
  31.     sal[sid].month=checkten(1,12);  
  32.     printf("please input the basic salary:________\b\b\b\b\b\b\b\b");  
  33.     sal[sid].basicsal=checkdb();  
  34.     printf("please input the additional salary:________\b\b\b\b\b\b\b\b");  
  35.     sal[sid].addsal=checkdb();  
  36.     printf("please input the subtract salary:________\b\b\b\b\b\b\b\b");  
  37.     sal[sid].subsal=checkdb();  
  38.   
  39.     sal[sid].theosal=sal[sid].basicsal+sal[sid].addsal;  
  40.     sal[sid].truesal=sal[sid].theosal-sal[sid].subsal;  
  41.     FreshSalName(sid);  
  42.     if(notfirst == 0) salcnt++;  
  43.     showsal(3,sal[sid].id,sal[sid].month);  
  44.     if(notfirst == 0) salcnt--;  
  45.     printf("BELOW INFORMATION SAVED SUCCESSFULlY \n");  
  46.     printf("PRESS ENTER TO CONTINUE.\n");getchar();getchar();  
  47. }  

 该段代码实现了排除鲁棒性的输入功能,并将教师信息中的姓名,学院,职称等,(如果工资信息存在)更新给工资信息,且在输入完成后,显示最新信息,以便查验。

 

3.3.2 delter() delsal()--删除教师信息及薪资信息

  1. void deleteter(char * id)  
  2. {  
  3.     // through swap and cnt-- to complete the delete operation  
  4.     swapter(&ter[tercnt-1],&ter[searchterid(id)]);  
  5.     tercnt--;  
  6. }  
  7. void deletesal(char * id)  
  8. {  
  9.     int i;  
  10.     for(i=0;i<salcnt;i++)  
  11.     {  
  12.         if(strcmp(sal[i].id,id) == 0)  
  13.         {  
  14.             swapsal(&sal[i],&sal[salcnt-1]);  
  15.             salcnt--;  
  16.         }  
  17.         FreshSalName(i); // to check bug  
  18.     }  
  19. }  

该删除方法为:交换当前元素和最后一位元素的全部信息(通过自定swap实现,后续将进行介绍),并将总元素个数的统计变量减一,以此实现该删除操作。

 

3.3.3 自定义简便SQL操作

    已在3.0.0中介绍完毕,此处不再赘述。

 

 

3.4 Algorithm Functions 概述

    该部分实现该程序的主要算法功能,接下来将一一介绍各函数的实现方法。

 

 

3.4.1 showter()--可选mode的教师信息列表打印函数

  1. int showter(int mode,char * cc)  
  2. {   // mode == 1: show all information  
  3.     // mode == 2: show NAME(tc)'s infromation  
  4.     // mode == 3: show ID(tc)'s information  
  5.     int re=-1;  
  6.     struct Teacher * tc;  
  7.     printf("\n---------------------------Basic Information---------------------\n");  
  8.     printf("|ID\t\t|NAME\t\t|COLLEGE\t|JOB\t\t|\n");  
  9.     printf("-----------------------------------------------------------------\n");    
  10.     for(tc=ter;tc<ter+tercnt;tc++)  
  11.     {  
  12.         if(mode == 1) printf("|%s\t|%-15s|%-15s|%-15s|\n",tc->id,tc->name,col_sec[tc->collegeid],job_sec[tc->jobid]);  
  13.         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]);  
  14.         if(mode == 3 && (strcmp(tc->id,cc) == 0) )   
  15.         {  
  16.             re=tc-ter; // return his cntid  
  17.             printf("|%s\t|%-15s|%-15s|%-15s|\n",tc->id,tc->name,col_sec[tc->collegeid],job_sec[tc->jobid]);  
  18.         }  
  19.     }  
  20.     printf("-----------------------------------------------------------------\n\n");  
  21.     return re;  
  22. }  
  23.   
  24.   
  25. void showsal(int mode,char * cc,int mon)  
  26. {   // mode == 1: show all information  
  27.     // mode == 2: show NAME(tc)'s infromation  
  28.     // mode == 3: show ID(tc)'s information  
  29.     // if mon == 0 then cout every information  
  30.     // if mon == 1~12 then just cout the month's information  
  31.     struct Salary * sa;  
  32.     printf("\n-------------------------------------------------Salary Information------------------------------------------------------\n");  
  33.     printf("|Month\t|ID\t\t|NAME\t\t|Basic($)\t|Allowance($)\t|Subtract($)\t|Theory($)\t|True($)\t|\n");  
  34.     printf("-------------------------------------------------------------------------------------------------------------------------\n");  
  35.     for(sa=sal;sa<sal+salcnt;sa++)  
  36.     {  
  37.         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,  
  38.             sa->name,sa->basicsal,sa->addsal,sa->subsal,sa->theosal,sa->truesal);  
  39.         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,  
  40.             sa->name,sa->basicsal,sa->addsal,sa->subsal,sa->theosal,sa->truesal);  
  41.         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,  
  42.             sa->name,sa->basicsal,sa->addsal,sa->subsal,sa->theosal,sa->truesal);  
  43.     }  
  44.     printf("-------------------------------------------------------------------------------------------------------------------------\n\n");  
  45. }  

当mode为1时,将展示所有教师的基本信息或薪水信息;当mode为2时,将展示姓名为所传入参数的教师的基本信息或薪水信息;当mode为3时,将展示ID为所传入参数的教师基本信息或薪水信息。

并且该函数利用了printf的格式化输出功能,保证列表的整齐与美观。

 

3.4.2 searchterid() searchsalid()--寻找所传id对应的实际索引以便后续操作

  1. int searchterid(char * id)  
  2. {  
  3.     int i;  
  4.     for(i=0; i < tercnt;i++)  
  5.     {  
  6.         if(strcmp(ter[i].id,id)== 0) return i;  
  7.     }  
  8.     return -1;  
  9. }  
  10.   
  11. int searchsalid(char * id,int month)  
  12. {  
  13.     int i;  
  14.     for(i=0;i<salcnt;i++)  
  15.     {  
  16.         if(strcmp(id,sal[i].id)==0 && sal[i].month == month) return i;  
  17.     }  
  18.     return -1;  
  19. }  

额外地,在考虑查询月份需求的情况下,特假设month参数,以选择特定的month进行输出(给定 month和id时才能唯一的确定一条记录)。

 

3.4.3 swapter()swapsal()swapcol()swapjob()--交换函数

全部内容交换函数,通过临时变量交换法实现,此处不做赘述。

 

3.4.4 sortter_id() sortsal_id()--排序函数

以id为序,对ter和sal的排序函数

  1. void sortter_id()  
  2. // make the ter list sorted by the id  
  3.     int i,j;  
  4.     for(i=0;i<tercnt;i++)  
  5.         for(j=tercnt-1;j>i;j--)  
  6.             if(strcmp(ter[j].id,ter[j-1].id)<0)            
  7.                 swapter(&ter[j],&ter[j-1]);  
  8. }  
  9.   
  10. void sortsal_id()  
  11. // make the sal list sorted by the 1:id 2:month  
  12.     int i,j;  
  13.     for(i=0;i<salcnt;i++)  
  14.         for(j=salcnt-1;j>i;j--)  
  15.         {  
  16.             if(strcmp(sal[j].id,sal[j-1].id)<0)            
  17.                 swapsal(&sal[j],&sal[j-1]);  
  18.             if(strcmp(sal[j].id,sal[j-1].id) == 0)  
  19.                 if(sal[j].month < sal[j-1].month)  
  20.                     swapsal(&sal[j],&sal[j-1]);   
  21.         }  
  22. }  

由于禁止使用C++的algorithm库及其sort函数,以及bool cmp() 排序规则,在此处我通过手写的方式,实现了相应的功能。基于冒泡排序和前面的swap函数实现。

 

3.4.5 calcolavg_sort() caljobavg_sort()--实现统计分析排序功能的函数

  1. void calcolavg_sort(int mon)  
  2. {  
  3.     int i,j;  
  4.     for(i=1;i<=Ncol;i++)  
  5.     {  
  6.         double thsum=0,trsum=0,cnt=0; // th->theory tr->true  
  7.   
  8.         for(j=0;j<salcnt;j++)  
  9.         {  
  10.             if(sal[j].collegeid == i && sal[j].month == mon)  
  11.             {  
  12.                 thsum += sal[j].theosal;  
  13.                 trsum += sal[j].truesal;  
  14.                 cnt++;  
  15.             }  
  16.         }  
  17.         col[i].collegeid = i;  
  18.         col[i].thavg= thsum?thsum/cnt:0;  
  19.         col[i].travg= trsum?trsum/cnt:0;  
  20.     }  
  21.   
  22.     for(i=1;i<=Ncol;i++)  
  23.         for(j=Ncol;j>i;j--)  
  24.         {  
  25.             if(col[j].travg > col[j-1].travg)              
  26.                 swapcol(&col[j],&col[j-1]);  
  27.             if(col[j].travg == col[j-1].travg)  
  28.                 if(sal[j].collegeid < sal[j-1].collegeid)  
  29.                     swapcol(&col[j],&col[j-1]);   
  30.         }  
  31. }  
  32.   
  33. void caljobavg_sort(int mon)  
  34. {  
  35.     int i,j;  
  36.     for(i=1;i<=Njob;i++)  
  37.     {  
  38.         double thsum=0,trsum=0,cnt=0; // th->theory tr->true  
  39.   
  40.         for(j=0;j<salcnt;j++)  
  41.         {  
  42.             if(sal[j].jobid == i && sal[j].month == mon)  
  43.             {  
  44.                 thsum += sal[j].theosal;  
  45.                 trsum += sal[j].truesal;  
  46.                 cnt++;  
  47.             }  
  48.         }  
  49.         job[i].jobid = i;  
  50.         job[i].thavg= thsum?thsum/cnt:0;  
  51.         job[i].travg= trsum?trsum/cnt:0;  
  52.     }  
  53.   
  54.     for(i=1;i<=Njob;i++)  
  55.         for(j=Njob;j>i;j--)  
  56.         {  
  57.             if(job[j].thavg > job[j-1].thavg)              
  58.                 swapjob(&job[j],&job[j-1]);  
  59.             if(job[j].travg == job[j-1].travg)  
  60.                 if(sal[j].jobid < sal[j-1].jobid)  
  61.                     swapjob(&job[j],&job[j-1]);   
  62.         }  
  63. }  

该段程序通过对所选职业或学院的相应工资信息进行累加,并存储在job和college两个结构体中,最后对这两个结构体进行排序实现以上功能。

 

3.4.6 FreshSalName()--同步sal与ter之间的信息

由于涉及到对salary信息与teacher信息的同步更新,设定此函数

  1. void FreshSalName(int salind)  
  2. {  
  3.     int i;  
  4.     for(i=0; i<tercnt;i++)  
  5.     {  
  6.           
  7.         if(strcmp(ter[i].id,sal[salind].id) == 0)   
  8.         {  
  9.             strcpy(sal[salind].name,ter[i].name);  
  10.               
  11.             sal[salind].collegeid=ter[i].collegeid;  
  12.             sal[salind].jobid=ter[i].jobid;  
  13.             break;  
  14.         }  
  15.           
  16.     }  
  17. }  

通过比对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,请加私信与我进行讨论,谢谢!

 

猜你喜欢

转载自blog.csdn.net/ShuoCHN/article/details/112061263