BFU《高校教師工資管理系統》課程設計

                                   北 京 林 業 大 學

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,請加私信與我進行討論,謝謝!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章