C語言職工工資管理系統

liqingyu1995發表於2015-09-20

一. 設計需求說明

一、職工工資管理系統功能設計要求

1. 輸入記錄:將每一個職工的姓名、ID 號以及基本工資、職務工資、崗位津貼、醫療保險、公積金的資料作為一個記錄。該軟體能建立一個新的資料檔案或給已建立好的資料檔案增加記錄。

2. 顯示記錄:根據使用者提供的記錄或者根據職工姓名顯示一個或幾個職工的各項工資和平均工資。

3. 修改記錄:可以對資料檔案的任意記錄的資料進行修改並在修改前後對記錄內容進行顯示。

4.查詢記錄:可以對資料檔案的任意記錄的資料進行查詢並在查詢前後對記錄內容進行顯示。

5. 刪除記錄:可刪除資料檔案中的任一記錄。

6.恢復記錄:能恢復被刪除的任一記錄。

7. 統計: (A) 計算各項工資平均工資及總工資, (B)統計符合指定條件(如職工工資前三項之和在2000 元以上、2000~1500 元、1500~1000 以內的工資職工人數及佔總職工人數的百分比。(C)按字元表格形式列印全部職工工資資訊表及平均工資(包括各項總的平均工資)

8.儲存資料檔案功能。

9.開啟資料檔案功能。

經過逐層逐塊、不斷細化、求精過程,編寫程式並進行測試、驗證,可以逐個模組地分開除錯,並透過檔案包含或用工程檔案的形式進行逐步聯合除錯。程式執行結果如下表所示(記錄個數至少)

二.模組設計分析

系統功能模組圖:

省略。

 工作程式分析

①輸入:輸入職工工資資料

 透過結構體的陣列來進行操作,先頭定義陣列em[],先輸入需要輸入的職工人數m,然後進入迴圈,每次迴圈將各項輸入結構體陣列對應項的對應成員中,當迴圈次數等於人數時,完成全部員工的資料輸入,退出迴圈。同時將資料儲存在ckerk_list檔案中並自動儲存至磁碟。

注:如首次使用,尚未輸入資料,請先輸入資料。輸入的資料將自動儲存。

再次選擇輸入功能時原資料將被覆蓋。

②儲存:將輸入的資料存入磁碟

    讀取檔案clerk_list,若檔案不存在,列印“開啟失敗並退出。若存在,則透過迴圈語句將輸入到結構體陣列的資料逐個輸入磁碟。

③讀取:讀取磁碟中的資料

  開啟檔案clerk_list ,若檔案不存在,列印“開啟失敗”並退出。若存在,讀取檔案中的資料,並返回職工人數。

④顯示:顯示職工工資資料

  先透過讀取函式的返回值確定職工人數m,再透過迴圈將員工工資資料逐個列印,當迴圈次數達到m時退出迴圈。其中總工資由程式計算,總工資=基本工資+職務工資+津貼-醫療保險-公積金

⑤刪除:刪除某員工的資料

  列印員工資料並提示輸入要刪除職工的姓名,輸入後若該職工不存在則列印“查無此人”;若存在,則顯示該職工資料並詢問是否確定刪除。若確定,則刪除。刪除時,透過對比輸入的姓名與資料中的姓名做對比從而確定要刪除的項i,從第i項開始,將後一項的各成員的值賦給前一項各對應的成員,完成對第i項的刪除。

⑥新增:新增新的員工資料而不覆蓋原有資料

列印原有職工資料,詢問要新增的職工人數並詢問是否確定新增。逐個逐項輸入員工資訊,之後程式計算其總工資。完成後顯示“新增成功”,列印新的員工資料並自動儲存。新增的方法為:定義一個相同型別的結構體陣列,將原有項複製後增添新的項,並儲存新的陣列。

⑦查詢:按ID好查詢與按姓名查詢員工資料

根據提示輸入要查詢的ID號或姓名,程式透過迴圈語句將輸入的數字與以儲存的結構體陣列中的資料對比,若相同,則列印“已找到”及該員工的資料;當迴圈次數等於人數時結束迴圈,若至結束迴圈時也沒有找到相同的,則列印“查無此人”。

⑧修改:修改特定員工的特定資料

列印員工資訊並提示輸入要修改資料的職工姓名。按提示確定要修改,確定要修改的專案,輸入要修改成的結果並將該結果賦給對應項的對應成員,完成對特定職工特定專案的修改。

⑨統計 

透過迴圈對結構體陣列中的每一項經行統計,計算工資總額為,將工資總額除以人數計算出平均工資。根據每名職工的資料計算基本工資、職務工資、津貼之和在1000-1500圓1500-2000圓2000圓以上的員工佔總員工的百分比。

三.源程式程式碼(附各部分解釋)

#include<stdio.h>

#include<windows.h>

#include<string.h>

#include<conio.h>

#define N 100

 

 

struct clerk

{

  int num;         //ID

  char name[20];   //姓名

  int jbgz;        //基本工資

  int zwgz;       //職務工資

  int jt;          // 津貼 

  int yb;         //醫療保險

  int gjj;         /公積金/

  int total;       //總工資

}em[100];       

void menu();

void input();

void save(int);

void display();

void del();

void add();

void search();

void search_num();

void search_name();

void modify();  

void sta();

void start(); /*定義各函式*/


void start() //開始介面

{

     system("cls");//清屏

     system("color 1E"); //設定文字顏色為黃色 背景色藍色

printf("\n\n\n\n\n\n");

printf("********************************************************************************");

printf("*****************************歡迎使用工資管理系統*****************************");

printf("*********************************************************************************\n\n\n\n\n");

printf("\t\t\t\t     製作: \n");

printf("\t\t\t\t        20116\n\n\n\n");

 

printf("\t\t\t    ***按任意鍵進入***\n");

 

}

void menu() //選單介面

{

system("cls");

system("color 1F"); 

printf("***選單***\n\n");

printf(">>>>>>>>>>>>>>>>>>>>>>>>>  1  輸入  \n\n");

printf(">>>>>>>>>>>>>>>>>>>>>>>>>  2  顯示  \n\n");

printf(">>>>>>>>>>>>>>>>>>>>>>>>>  3  查詢  \n\n");

printf(">>>>>>>>>>>>>>>>>>>>>>>>>  4  刪除  \n\n");

printf(">>>>>>>>>>>>>>>>>>>>>>>>>  5  新增  \n\n");

printf(">>>>>>>>>>>>>>>>>>>>>>>>>  6  修改  \n\n");

printf(">>>>>>>>>>>>>>>>>>>>>>>>>  7  統計  \n\n");

printf(">>>>>>>>>>>>>>>>>>>>>>>>>  8  退出  \n\n");

printf("說明:*如首次使用 尚未輸入資料 請先輸入資料 \n      *輸入的資料將自動儲存 \n      *再次選擇輸入功能時原資料將被覆蓋\n\n");

}

void input()   /*錄入函式*/

{

    int i,m;

    system("cls");

   printf("職工人數(1--100):\n");

    scanf("%d",&m);

   

for (i=0;i<m;i++)

    {

   printf("請輸入職工號: ");

   scanf("%d",&em[i].num);

 

   printf("請輸入姓名:  ");

   scanf("%s",&em[i].name);

  getchar();

 

   printf("請輸入基本工資:  ");

   scanf("%d",&em[i].jbgz);

  

printf("請輸入職務工資:  ");

   scanf("%d",&em[i].zwgz);

   printf("請輸入津貼:  ");

   scanf("%d",&em[i].jt);

   printf("請輸入醫療保險:  ");

   scanf("%d",&em[i].yb);

printf("請輸入公積金:  ");

   scanf("%d",&em[i].gjj);  

em[i].total=((em[i].jbgz)+(em[i].zwgz)+(em[i].jt)-(em[i].yb)-(em[i].gjj));//計算總工資

   printf("\n");//計算總工資

    }

    printf("\n建立完畢!\n");

       save(m);//儲存職工人數m

}

void save(int m)  /*儲存檔案函式*/

{

  int i;

  FILE*fp;   //宣告fp是指標,用來指向FILE型別的物件

  if ((fp=fopen("clerk_list","wb"))==NULL) //開啟職工列表檔案為空

  {

   printf ("開啟失敗\n");

      exit(0);

  }

 

for (i=0;i<m;i++) /*將記憶體中職工的資訊輸出到磁碟檔案中去*/

    if (fwrite(&em[i],sizeof(struct clerk),1,fp)!=1)//寫入資料塊   &em[i]:是要輸出資料的地址  sizeof(struct clerk):獲取一個單體的長度  1:資料項的個數  fp:目標檔案指標

    printf("檔案讀寫錯誤\n");

    fclose(fp);// 緩衝區內最後剩餘的資料輸出到磁碟檔案中,並釋放檔案指標和有關的緩衝區

} 

int load()  /*匯入函式  int*/

{

     FILE*fp;

  int i=0;

    if((fp=fopen("clerk_list","rb"))==NULL)

  {

   printf ("cannot open file\n");

      exit(0);

  }

  else 

  {

   do 

   {

         fread(&em[i],sizeof(struct clerk),1,fp); //讀取

       i++;

   }

   while(feof(fp)==0);  //檢測流上的檔案結束符

  }

 

fclose(fp);

  return(i-1);//返回人數

}


void display()  /*瀏覽函式*/

{

 

  int i,sum=0;

  int m=load();

  system("cls");

  printf("職工號   姓名   基本工資  職務工資   津貼    醫療保險  公積金   總工資 \n");

  for(i=0;i<m;i++) /*m為輸入部分的職工人數*/

  {printf("\n  %-6d%-6s  %-8d  %-8d  %-8d  %-8d  %-8d %-8d  ",em[i].num,em[i].name,em[i].jbgz,em[i].zwgz,em[i].jt,em[i].yb,em[i].gjj,em[i].total);

   sum+=em[i].total;//計算員工總工資之和

  }

   printf("\n\n職工平均工資為:%d \n",sum/m);

}

void del()   /*刪除函式 */

{

  int m=load();

  int i,j,n,t,button;

  char name[20];

 

printf("\n 原來的職工資訊:\n");

     display(); //顯示刪除前的員工資訊

     printf("\n");

 

printf("按姓名刪除:\n");

  scanf("%s",name);

  for(button=1,i=0;button&&i<m;i++)//主函式中確定button==1時各函式才可以被呼叫

  {

   if(strcmp(em[i].name,name)==0)//按員工姓名查詢到某員工 並調出其資料

   {

    printf("\n此人原始記錄為:\n");//顯示選定員工的資訊

    printf("職工號   姓名   基本工資  職務工資   津貼    醫療保險  公積金   總工資 \n");

    printf("\n  %-6d%-6s  %-8d  %-8d  %-8d  %-8d  %-8d %-8d  ",em[i].num,em[i].name,em[i].jbgz,em[i].zwgz,em[i].jt,em[i].yb,em[i].gjj,em[i].total);  

    printf("\n確定刪除 請按1,不刪除請按0\n");  

    scanf("%d",&n);

             if(n==1)

    {

      for(j=i;j<m-1;j++)//從第i項開始 將後一項的各成員的值賦給前一項各對應的成員 完成對第i項的刪除

      {

     strcpy(em[j].name,em[j+1].name);

                 em[j].num=em[j+1].num;

                 em[j].jbgz=em[j+1].jbgz;

                 em[j].zwgz=em[j+1].zwgz;

                 em[j].jt=em[j+1].jt;

                em[j].yb=em[j+1].yb;  

                em[j].gjj=em[j+1].gjj;

                em[j].total=em[j+1].total;

      }

     . button=0;

    }

   }

  }

  if(!button)//button==0表明刪除已完成

     m=m-1;//總員工數減少一人

  else

     printf("\n查無此人!\n");

     printf("\n 刪除後的所有職工資訊:\n");

     save(m);     //呼叫儲存函式

     display();  //呼叫瀏覽函式

 

printf("\n繼續刪除請按1,不再刪除請按0\n");

  scanf("%d",&t);

  switch(t)

  {

     case 1:del();break;

     case 0:break;

     default :break;

  }

}


void add()/*新增函式*/

{

  FILE*fp;

  int n;

     int count=0;

     int i;

     int m=load();

    

printf("\n 原來的職工資訊:\n");

     display();  

    printf("\n");

     fp=fopen("emploee_list","a");

     printf("請輸入想增加的職工數:\n");//確定要加入的職工數n

  scanf("%d",&n);

     for (i=m;i<(m+n);i++)//新增n名員工的資訊

   {

   printf("\n 請輸入新增加職工的資訊:\n");

   printf("請輸入職工號:  ");

   scanf("%d",&em[i].num);

   printf("\n");

         printf("請輸入姓名:  ");

      scanf("%s",em[i].name);

         getchar();

         printf("請輸入基本工資:  ");

      scanf("\t%d",&em[i].jbgz);

         printf("請輸入職務工資:  ");

      scanf("%d",&em[i].zwgz);

      printf("請輸入津貼:  ");

      scanf("%d",&em[i].jt);

      printf("請輸入醫療保險:  ");

      scanf("\t%d",&em[i].yb);

       printf("請輸入公積金:  ");

      scanf("%d",&em[i].gjj);

       em[i].total=( em[i].jbgz+ em[i].zwgz + em[i].jt- em[i].yb- em[i].gjj);//計算該員工總工資

         printf("\n");

      count=count+1;

  

printf("已增加的人數:\n");

      printf("%d\n",count);

  }

     printf("\n新增成功\n"); 

     m=m+count;//將新新增員工的人數加到總員工人數中

  printf("\n增加後的所有職工資訊:\n");

  printf("\n");

  save(m);

     display();//顯示新增後的資訊

    fclose(fp);

}


void search()/*查詢函式*/

{

     int t,button;

  system("cls");//清屏

 

do

  {

     printf("\n按工號查詢\n按姓名查詢\n回主選單\n");

     scanf("%d",&t);

     if(t>=1&&t<=3)

     {

     button=1;

     break;

     }

     else

     {

    button=0;

    printf("輸入錯誤");

     }

  }

     while(button==0);//回到查詢選擇項

     while(button==1)

  {

     switch(t)//選擇查詢方式

     { 

      case 1:printf("按工號查詢\n");search_num();break;

      case 2:printf("按姓名查詢\n");search_name();break;

       case 3:main();break;

      default:break;

     }

    

  }

 

}


void search_num()//按職工號查詢

{

  int a;

  int i,t;

  int m=load();

  printf("請輸入要查詢的職工號:\n");

  scanf("%d",&a);

  for(i=0;i<m;i++)

  if(a==em[i].num)

 {  

  printf("職工號   姓名   基本工資  職務工資   津貼    醫療保險  公積金   總工資 \n");

  printf("\n  %-6d%-6s  %-8d  %-8d  %-8d  %-8d  %-8d %-8d  ",em[i].num,em[i].name,em[i].jbgz,em[i].zwgz,em[i].jt,em[i].yb,em[i].gjj,em[i].total);   

  break;

 

 }

   if(i==m)  

   printf("\n對不起,查無此人\n");

   printf("\n");

   printf("返回查詢函式請按1,繼續查詢職工號請按2\n");

   scanf("%d",&t);

   switch(t)

   { 

   case 1:search();break;

   case 2: break;

   default:break;

   }

}

void search_name()

{

  char name[30];

  int i,t;

  int m=load();

  printf("請輸入姓名:\n");

  scanf("%s",name);

  for(i=0;i<m;i++)

   if(strcmp(em[i].name,name)==0)

 {

    printf("\n已找到,其記錄為:\n");

     printf("職工號   姓名   基本工資  職務工資   津貼    醫療保險  公積金   總工資 \n");

     printf("\n  %-6d%-6s  %-8d  %-8d  %-8d  %-8d  %-8d %-8d  ",em[i].num,em[i].name,em[i].jbgz,em[i].zwgz,em[i].jt,em[i].yb,em[i].gjj,em[i].total);      

 }

   if(i==m) 

   printf("\n\n");

   printf("\n");

   printf("返回查詢選單請按1,繼續查詢姓名請按2\n");

   scanf("%d",&t);

  switch(t)

  { 

   case 1:search();break;

   case 2:break;

   default :break;

  }

 }


void modify() /*修改函式*/

{

     int num;

     char name[20];

     int jbgz;  

     int zwgz;

     int jt;

     int yb;

     int gjj;

     int b,c,i,n,t,button; 

  int m=load();

     system("cls");

 

     printf("\n 原來的職工資訊:\n");

     display(); 

  printf("\n");

    

printf("請輸入要修改的職工的姓名:\n");

  scanf("%s",name);

  for(button=1,i=0;button&&i<m;i++)

  {

   if(strcmp(em[i].name,name)==0)

   {

     printf("\n此人原始記錄為:\n");

      printf("職工號   姓名   基本工資  職務工資   津貼    醫療保險  公積金   總工資 \n");

      printf("\n  %-6d%-6s  %-8d  %-8d  %-8d  %-8d  %-8d %-8d  ",em[i].num,em[i].name,em[i].jbgz,em[i].zwgz,em[i].jt,em[i].yb,em[i].gjj,em[i].total);    

      printf("\n確定 按1 ; 不修改請按0\n");

      scanf("%d",&n);

             if(n==1)

    {

                printf("\n需要進行修改的選項\n 1.職工號 2.姓名 3.基本工資 4.職務工資 5.津貼 6.醫療保險 7.公積金 8.返回上層\n");  

                printf("請選擇序號1-8:\n");  

                scanf("%d",&c);  

                if(c>8||c<1)  

          printf("\n選擇錯誤,請重新選擇!\n");  

    }

         button=0;

   }

        

  }

     if(button==1)

  printf("\n查無此人\n");  

    

do  

  {

   switch(c)      /*因為當找到第i個職工時,for語句後i自加了1,所以下面的應該把改後的資訊賦值給第i-1個人*/

   {  

            case 1:printf("職工號改為: ");

                scanf("%d",&num);

              em[i-1].num=num;

                   break;  

            case 2:printf("姓名改為: ");

                               scanf("%s",name);

                               strcpy(em[i-1].name,name); 

                               break;  

            case 3:printf("基本工資改為: ");

                                getchar();

                                scanf("%d",&jbgz);

                                em[i-1].jbgz=jbgz;

               em[i-1].total=( em[i-1].jbgz+ em[i-1].zwgz + em[i-1].jt- em[i-1].yb- em[i-1].gjj);

            break;  

            case 4:printf("職務工資改為: ");

       scanf("%d",&zwgz);

       em[i-1].zwgz=zwgz;

        em[i-1].total=( em[i-1].jbgz+ em[i-1].zwgz + em[i-1].jt- em[i-1].yb- em[i-1].gjj);

            break;  

            case 5:printf("津貼改為: ");

       scanf("%d",&jt);

       em[i-1].jt=jt; 

       em[i-1].total=( em[i-1].jbgz+ em[i-1].zwgz + em[i-1].jt- em[i-1].yb- em[i-1].gjj);

            break;  

            case 6:printf("醫療保險改為: ");

       scanf("%d",&yb);

       em[i-1].yb=yb;

       em[i-1].total=( em[i-1].jbgz+ em[i-1].zwgz + em[i-1].jt- em[i-1].yb- em[i-1].gjj);

            break;  

            case 7:printf("公積金改為: ");

       scanf("%d",&gjj);

       em[i-1].gjj=gjj;

       em[i-1].total=( em[i-1].jbgz+ em[i-1].zwgz + em[i-1].jt- em[i-1].yb- em[i-1].gjj);

            break;  

            case 8:modify(); 

            break;  

   } 

  

printf("\n");

   printf("\n\n 確定修改 請按1 ; 重新修改 請按2:  \n"); 

   scanf("%d",&b);

  }   

    while(b==2);

    printf("\n修改後的所有職工資訊:\n");

    printf("\n");

    save(m);

   

display();

    printf("\n繼續修改 ,不再修改請按0\n");

    scanf("%d",&t);

    switch(t)

  {

     case 1:modify();break;

     case 0:break;

     default :break;

  }

}

void sta()//統計函式

{

  int i;

  int sum=0; 

  int a=0,b=0,c=0;

  int m=load();

system("cls");//清屏函式

  for(i=0;i<m;i++) /*m為輸入部分的職工人數*/

  {sum+=em[i].total;

   if((em[i].total)<=1500&&em[i].total>=1000) 

     {a++;}

   if(em[i].total>1500&&em[i].total<=2000) 

     {b++;}

   if(em[i].total>2000) 

     {c++;}

}

 

printf("\n\n工資總額為:%d\n",sum);

printf("平均工資為:%d\n",sum/m);

printf("\n基本工資、職務工資、津貼之和\n");

printf("1000-1500圓的員工佔總員工的百分之%d\n",a*100/m); 

printf("1500-2000圓的員工佔總員工的百分之%d\n",b*100/m); 

printf("2000圓以上的員工佔總員工的百分之%d\n",c*100/m);

printf("\n\n按任意鍵繼續");

getch();

menu();

}


void main()//主函式

{   

int n,button;

  char a; 

  start();

getch();

  menu();  

  do

  {

     printf("功能選擇(1--8):\n");

     scanf("%d",&n);

     if(n>=1&&n<=7)

     {

     button=1;

     break;

     }

     else

     {

    button=0;

    printf("您輸入有誤,請重新選擇!");

     }

  }

     while(button==0);

     while(button==1)

     { 

switch(n)

   {

        case 1: input();break;

        case 2: display();break;

        case 3: search();break; 

        case 4:del();break;

        case 5: add();break;

        case 6:modify();break;

        case 7:sta();break;

        case 8:exit(0);break;

        default :break;

   }

  

getchar();

   printf("\n");

   printf("按任意鍵繼續\n");

   getch();

      system("cls");  /*清屏*/

      menu(); /*呼叫選單函式*/

      printf("功能選擇(1--8):\n");

      scanf("%d",&n);

      printf("\n");

     }

}

心得體會

透過這兩週的c語言課程設計,我加深了對c語言程式設計的理解,使自己的操作更加熟練,發現了自己的不足,為自己今後的繼續學習指明瞭方向。在這次課程設計中,我鞏固所了學過的知識,能用匯編語言熟練地運用順序、選擇、迴圈三大結構,進一步掌握結構體陣列的使用,檔案函式的使用,掌握了子程式的定義及呼叫。並在除錯過程中不斷發現與改正錯誤,完善演算法,改進使用者體驗等等。除錯索然繁瑣而艱苦,但極大的促進了我程式設計能力的提高。

由於自己目前能力有限,該程式還有諸多不足,感謝指正。感謝老師的悉心教導與細緻的幫助。雖然c語言的課程與課程設計都已結束,但透過這次課程設計我也發現了差距,並將在未來努力學習,積極實踐,使自己能真正的掌握運用c語言。 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30211155/viewspace-1804602/,如需轉載,請註明出處,否則將追究法律責任。

相關文章