C語言職工檔案管理系統(tǒng)-500多行代碼.doc
1程序的總體設(shè)計職工檔案管理系統(tǒng)設(shè)計,每個職工是一條記錄,包括編號,姓名,性別,出生年月,所在部門,職稱,工資級別、電話等。系統(tǒng)可實現(xiàn)以下功能:1、輸入功能:輸入每一位職工記錄,將其信息存入文件中。2、顯示功能:完成全部職工記錄的顯示。3、查找功能:完成按編號或姓名查找職工的相關(guān)記錄,并顯示。2. 數(shù)據(jù)結(jié)構(gòu)對于這個職工檔案系統(tǒng)的設(shè)計,我主要采用結(jié)構(gòu)體存放不同類型的數(shù)據(jù),運用數(shù)組對各數(shù)據(jù)進行控制,而所有數(shù)據(jù)(除ID外)都以字符型的形式存放,這樣方便存入中文數(shù)據(jù)。本程序用指針相對較少,事實上,我只在文件的保存函數(shù)上用了指針。只要是因為我們對指針了解相對較少,而且指針相對容易出錯誤,而這個程序用結(jié)構(gòu)體和數(shù)組就可以很好地完成。3. 函數(shù)原型聲明的說明(功能,參數(shù),返回值)1.主函數(shù) void main()主函數(shù)的主意作用是調(diào)用函數(shù)以實現(xiàn)程序的預期功能,主函數(shù)有各函數(shù)的聲明調(diào)用。主函數(shù)用switch語句對各函數(shù)進行調(diào)用。2添加函數(shù):void append()該函數(shù)是無參函數(shù),主要功能是添加職工,由于界面為DOS的命令界面,為了使添加更加人性化,我采用先確認添加人數(shù),再對每個員工的每條信息,逐個添加,這樣可以減少錯誤的發(fā)生和加快輸入速度。員工添加后可用保存函數(shù),將其數(shù)據(jù)保存到指定文件中。3查找函數(shù): void search()該函數(shù)是無參函數(shù),主要功能是查找員工,可按編號或姓名查找職工的相關(guān)記錄,按姓名查找時采用字符串處理函數(shù)strcmp()進行比較,這樣可以用兩種方法查找職工信息。4輸出函數(shù):void output()該函數(shù)是無參函數(shù),主要功能是輸出全部員工的信息,用for語句進行輸出。5刪除函數(shù):void delete()該函數(shù)是無參函數(shù),主要功能是刪除指定員工的全部信息,該函數(shù)相對較復雜,用for語句對刪除后該員工后的員工的序號進行排列。6修改函數(shù):void modify()該函數(shù)是無參函數(shù),主要功能是修改指定員工的信息,該函數(shù)有密碼操作,要輸入密碼后才能進入修改界面,密碼操作采用while語句,用getch()輸入密碼,可以將密碼隱藏。這里getch()函數(shù)要調(diào)用conio.h文件。7保存函數(shù):void save()該函數(shù)是無參函數(shù),主要功能是保存添加的員工信息到指定文件,該函數(shù)用到了指針和文件的內(nèi)容。8主菜單函數(shù):void showmenu()該函數(shù)是無參函數(shù),主要功能是提供美觀的菜單界面。9文檔導入函數(shù):void read()該函數(shù)是無參函數(shù),主要功能是導入文件中的職工檔案信息。9數(shù)據(jù)排序函數(shù):void sort()該函數(shù)是無參函數(shù),主要將職工數(shù)據(jù)排序,分按編號排序和工資排序,工資排序又分從高到低和從低到高兩種。二、詳細設(shè)計1.main()流程圖修改數(shù)據(jù)輸入密碼由低到高由高到低按工資排序按編號排序?qū)霐?shù)據(jù)Switch語句查找函數(shù)輸出數(shù)據(jù)修改函數(shù)開始主函數(shù)刪除數(shù)據(jù)保存數(shù)據(jù)數(shù)據(jù)排序添加數(shù)據(jù)主菜單函數(shù)按姓名查找按編號查找三、測試及調(diào)試(測試方案、存在的問題及解決方法)測試方案、存在的問題及解決方法 我用的是visual C+ 6.0進行編譯和測試的,主要觀察程序運行的錯誤及找出錯誤發(fā)生的原因,還有各函數(shù)的功能的實現(xiàn)以及部分變量在程序運行時的變化。采取逐個函數(shù)測驗的方法 ,雖然比較耗時間,但是我實在沒有找到可以檢查我的海量錯誤的方法。下面是某此調(diào)試的截圖。 可以看到,這時候幾乎什么錯誤都有,低級的錯誤數(shù)不清,高級的錯誤無法數(shù),在這樣的局勢下,我仍然心靜如水地檢查錯誤,下面介紹我遇到的問題及其解決方案。 我主要遇到了三個函數(shù)問題,第一,我原本想用數(shù)組代替指針,這樣可以更好的檢查錯誤,但是后來的的數(shù)據(jù)保存就遇到了問題,老是無法正確的保存數(shù)據(jù),所以還是用了個FILE *fp,當然也為此狂看了文件一章,最后在數(shù)據(jù)導入也用到了指針和文件。第二,題目本沒有要求寫刪除函數(shù)也沒有要求寫排序函數(shù),也許修改函數(shù)能夠代替刪除函數(shù)的一部分功能,但是無法減少職工的數(shù)目,這個對于想裁員的公司不利,所以,我又想了一個刪除函數(shù)。寫刪除函數(shù)遇到的問題是,我刪除了編號為2的函數(shù),如何把2后面的同志移到前面來,而1不動,后來還是用最笨的for語句搞定了,據(jù)說這里可以用鏈表很美妙地完成,但是也可以不用鏈表。排序函數(shù)是最后加上去的,一個原因是我的程序不夠500行,就完成了功能,后來要求盡情發(fā)揮,我就用了排序函數(shù),這個函數(shù)相對簡單,用的是我們學過的起泡法排序,有按照編號和工資排序兩種方式,也用到了switch語句,這樣是程序的功能更加完善了。第三,密碼的問題,密碼函數(shù)是個比較嚴肅的函數(shù),為此不能敷衍了事用個while語句和字符串處理函數(shù)搞定,這樣密碼是明文的,很別扭。所以,我又加了一個不熟悉的頭文件#include <conio.h>,調(diào)用了這個文件里的getch()函數(shù),這個函數(shù)能夠不顯示你輸入的字符,很有保密特性。 程序設(shè)計其實是最大的問題,起初的兩三天我根本就不知道從哪里入手,后來參考到可以用switch語句對各功能函數(shù)很好的利用,這里還用到了break語句,感覺,課堂上沒講的東西就是這么有用??! 關(guān)于如何輸入數(shù)據(jù)信息的問題,我起初準備用一個scanf語句,輸入全部的職工信息,都是后來發(fā)現(xiàn)這樣極易出現(xiàn)輸入格式不正確的問題,后來就考慮用一個一個數(shù)據(jù)輸入的方法,雖然這樣做使代碼長度加長了一些,但是這樣輸入簡單明了更加人性化,所以我最終采用了逐個數(shù)據(jù)輸入的方法。 我還用宏定義定義了一個最大員工數(shù)MAX_NUM,這樣能夠使程序更高效率更準確地運行,而且改變最大員工數(shù)業(yè)很方便。 最后談?wù)務(wù){(diào)試錯誤的問題,上面已經(jīng)曬了我的錯誤截圖,感覺這些錯誤確實很震撼人,有時候就一個字符串函數(shù)應(yīng)用錯誤,找了半天,居然發(fā)現(xiàn)strcmp前面忘記加“!”了,還有諸如忘記寫“;”“”,最頭痛的還是把%s寫成%d,這樣程序能夠運行,就是系統(tǒng)告訴你內(nèi)存錯誤,搞得我以為電腦壞了,調(diào)了半天電腦,這就足夠悲劇的。最后還是一點一點地去檢查,不怕花費時間,就怕那些小東西太不入眼了。越是小的問題,可能浪費的時間就越讓人感到悲憤,所以,細心檢查永遠是解決此類問題的良方。 四、小結(jié)(收獲和建議)通過本次課程設(shè)計我不僅溫習了C程序設(shè)計課程的主體知識,還鍛煉了對錯誤的承受能力,而且這個題目是我這輩子做過的最大的題目,搞了一個多星期才有一點點眉目,讓人感到前途特別渺茫,也催迫著我不斷前進。 開始時,對這個題目完全無從下手,后來列出了主函數(shù)和結(jié)構(gòu)體,就慢慢算入門了,成天趴在電腦里,電腦前放著那本綠色的程序設(shè)計的書,外面冷風嗖嗖,鞭炮響起。明天就是除夕了,我要趕在春節(jié)前把這個題目做完。而現(xiàn)在函數(shù)全部寫出來了,且運行的相當成功,幾個特殊的功能函數(shù)也奇跡般的起作用了,小小的成功給了我大大的喜悅。這個時候,電腦不是機器,數(shù)據(jù)不是抽象,一切都像春風一樣。 調(diào)試程序的時候情緒一直十分難控,一聲聲嘆息加上使勁敲打鍵盤的聲音還有怒目對視屏幕,這樣感覺在無盡的黑暗中尋找黎明。現(xiàn)在黎明的曙光已經(jīng)出現(xiàn),感覺一切的努力都是那么值得,心胸豁然開朗。當然也有沒有解決的問題,就是我的密碼不能夠在程序運行的時候修改只能夠在源程序上修改,后來想了很久也沒有找到好的辦法。 建議,由于在學校時沒有上過幾次實驗課,理論的東西已經(jīng)慢慢淡忘。所以建議以后此類的課盡量在實驗室上好些,還有感覺只有一個題目沒有啥挑戰(zhàn)性,應(yīng)該多布置幾個附件:主要源程序代碼(需打?。?*C語言課程設(shè)計任務(wù)書:職工檔案管理系統(tǒng)設(shè)計*/#include <stdio.h>#include<string.h>#include <stdlib.h>#include <conio.h>#include <stdlib.h>#defineMAX_NUM900 struct worker int ID;char Birth20;char Sex20;char Name30;char Telenum20;int Wage;char Department30;char Job30; workMAX_NUM;void main() void showmenu(); /* 聲明主菜單函數(shù) */void append(); /* 聲明添加函數(shù) */ void search(); /* 聲明查找函數(shù) */ void output(); /* 聲明輸出函數(shù) */ void modify(); /* 聲明修改函數(shù) */ void deletes(); /* 聲明刪除函數(shù) */ void save(); /* 聲明保存函數(shù) */ void read(); /* 聲明錄入函數(shù) */ void sort(); /* 聲明排序存函數(shù) */ int m; showmenu();scanf("%d",&m);for(;m>=0&&m<=8;)switch(m)case 1: append(); /* 用戶選擇 1 號菜單,程序執(zhí)行 添加的數(shù)據(jù)文件的函數(shù) */break;case 2: search();/* 用戶選擇 2號菜單,程序執(zhí)行 查找數(shù)據(jù)的函數(shù) */break;case 3: modify();/* 用戶選擇 3 號菜單,程序執(zhí)行 修改數(shù)據(jù)的函數(shù) */break;case 4: deletes();/* 用戶選擇 4號菜單,程序執(zhí)行 刪除數(shù)據(jù)的函數(shù) */break;case 5: output();/* 用戶選擇 5號菜單,程序執(zhí)行輸出數(shù)據(jù)錄的函數(shù) */break;case 6: save();/* 用戶選擇 6 號菜單,程序執(zhí)行保存數(shù)據(jù)的函數(shù) */break;case 7: read();/* 用戶選擇7 號菜單,程序執(zhí)行 讀取文件的函數(shù) */break;case 8: sort();/* 用戶選擇8 號菜單,程序執(zhí)行 排序數(shù)據(jù)的函數(shù) */break;case 0: exit(0);/* 用戶選擇 3 號菜單,程序執(zhí)行退書的函數(shù) */printf("nn操作完畢,請再次選擇!");default:printf("錯誤,重新輸入n");showmenu();scanf("%d",&m); /* 主菜單函數(shù) */ void showmenu()/* 顯示 主菜單,并返回用戶所選擇的 菜單項 的 編號 */ printf(" *n"); printf(" 職工檔案管理系統(tǒng)n"); printf(" -設(shè)計者:陳文凱-n"); printf(" *n"); printf(" n"); printf(" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& n"); printf(" & 1,添加職工 5,輸出職工 & n"); printf(" & 2,查找職工 6,保存職工 & n"); printf(" & 3,修改職工 7,讀取檔案 & n"); printf(" & 4,刪除職工 8,職工排序 & n"); printf(" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& n"); printf("-退出,請按0-n");printf("請選擇(0-8):"); /* 添加函數(shù) */ void append()int number,i;FILE *fp;char filepnMAX_NUM;system("cls"); printf("n您選擇的是添加職工!n");printf("n請輸入本次添加的職工人數(shù): ");scanf("%d",&number); if(number>MAX_NUM)printf("您輸入的人數(shù)太多,大于 %d 人!n",MAX_NUM); for(i=0;i<number;i+)printf("n請輸入第%d個職工的編號:t",i+1);scanf("%d",&worki.ID);printf("t職工檔案:n");printf("tt姓名:");scanf("%s",&worki.Name);printf("tt出生年月:");scanf("%s",&worki.Birth);printf("tt電話:");scanf("%s",&worki.Telenum); printf("tt性別:");scanf("%s",&worki.Sex);printf("tt工資:");scanf("%d",&worki.Wage);printf("tt部門:");scanf("%s",&worki.Department);printf("tt職稱:");scanf("%s",&worki.Job);printf("n您的輸入是:n"); printf(" *職工檔案信息庫*n");printf(" 序號 編號 姓名 出生年月 電話t 性別 t工資t部門t職稱n");for(i=0;i<number;i+)printf(" %d %d %s %st%st%st%dt%st%sn",i+1,worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job);printf(" *n");printf("n"); /* 查找函數(shù) */ void search()system("cls"); int number=MAX_NUM,findID,v,i;char findName30;printf("n您選擇的是檔案查詢!n");printf(" *請選擇查詢方式*n");printf("t t 1-按編號查找;t t t t 2-按姓名查找n"); /*以下可以修改為子菜單方式:1-按編號查找,2-按姓名查找*/printf(" *n");printf("請選擇:");scanf("%d",&v);switch(v) case 1: system("cls"); printf("n您選擇的是按編號查找!n");printf("n請輸入職工的編號: ");scanf("%d",&findID);for(i=0;i<number;i+)if(worki.ID=findID)break;if(i<number)printf("查找結(jié)果如下:n");printf("t編號t姓名 t出生年月t電話t 性別t工資t部門t職稱n");printf("t%dt%s t%st%st %st%dt%st%sn",worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job); else printf("您輸入的編號不存在!n");break;case 2: system("cls"); printf("n您選擇的是按姓名查找!n");printf("n請輸入職工的姓名: ");scanf("%s",&findName);for(i=0;i<number;i+)if(!strcmp(worki.Name,findName)break;if(i<number)printf("查找結(jié)果如下:n");printf("t編號t姓名 t出生年月t電話t 性別t工資t部門t職稱n");printf("t%dt%s t%st%st %st%dt%st%sn",worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job); else printf("您輸入的姓名不存在!n");break; /* 輸出函數(shù) */ void output() int i,number=MAX_NUM;system("cls"); printf("查找結(jié)果如下:n"); printf("t編號t姓名 t出生年月t電話t 性別t工資t部門t職稱n"); for(i=0;i<number;i+) printf("t%dt%s t%st%st %st%dt%st%sn",worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job); void deletes()int findID,i,j,number=MAX_NUM; system("cls"); printf("n您選擇的是檔案刪除!n");printf("n請輸入職工的編號: ");scanf("%d",&findID);for(i=0;i<number;i+)if(worki.ID=findID)break;printf("t編號t姓名 t出生年月t電話t 性別t工資t部門t職稱n");if(i<number) for(j=i;j<number-1;j+) workj.ID=workj+1.ID; strcpy(workj.Name,workj+1.Name); strcpy(workj.Telenum,workj+1.Telenum); strcpy(workj.Birth,workj+1.Birth); strcpy(workj.Sex,workj+1.Sex); workj.Wage=workj+1.Wage; strcpy(workj.Department,workj+1.Department); strcpy(workj.Job,workj+1.Job);for(i=0;i<number-1;i+)printf("t%dt%s t%st%st %st%dt%st%sn",worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job);elsefor(i=0;i<number-1;i+)printf("t%dt%s t%st%st %st%dt%st%sn",worki.ID,worki.Name,worki.Telenum,worki.Birth,worki.Sex,worki.Wage,worki.Department,worki.Job);number-; /* 修改函數(shù) */ void modify()int findID,i,number=MAX_NUM; system("cls"); char yz9,psw9="12345678"printf("n您選擇的是檔案修改!n");while(1) printf("n請輸入密碼!n"); for(i=0;i<9;i+) yzi=getch(); printf("*"); if(yzi=r) yzi=0; break; if(!strcmp(psw,yz) printf("n密碼正確!n"); break; else printf("密碼錯誤,請重輸!n"); printf("n請輸入職工的編號: ");scanf("%d",&findID);for(i=0;i<number;i+)if(worki.ID=findID)break;if(i<number) printf("t姓名 t出生年月電話tt 性別t工資t部門t職稱n"); printf("原檔案:nt%d t%st%st %st%dt%st%sn",worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job);printf("請輸入新檔案:n ");printf("tt姓名:");scanf("%s",&worki.Name);printf("tt出生年月:");scanf("%s",&worki.Birth);printf("tt電話:");scanf("%s",&worki.Telenum); printf("tt性別:");scanf("%s",&worki.Sex);printf("tt工資:");scanf("%d",&worki.Wage);printf("tt部門:");scanf("%s",&worki.Department);printf("tt職稱:");scanf("%s",&worki.Job);printf("n您的輸入是:n"); printf(" *職工檔案信息庫*n");printf(" 序號 編號 姓名 出生年月 電話t 性別 t工資t部門t職稱n");for(i=0;i<number;i+)printf(" %d %d %s %st%st%st%dt%st%sn",i+1,worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job);printf(" *n");printf("n");elseprintf("您輸入的編號不存在!n"); /* 保存函數(shù) */ void save() FILE *fp;char filepnMAX_NUM;int number=MAX_NUM,i; system("cls");printf("您選擇的是職工檔案的保存!n");printf("請輸入文件路徑及文件名:");scanf("%s",filepn);if(fp=fopen(filepn,"w+")=NULL)printf("不能打開文件!n");for (i=0;i<number;i+) if (fwrite(&worki,sizeof(struct worker),1,fp)!=1) printf("寫入文件錯誤!n"); fclose(fp);printf("文件已經(jīng)保存!n"); /* 讀取檔案函數(shù) */ void read() FILE *fp;char filepnMAX_NUM;int number=MAX_NUM,i; system("cls");printf("您選擇的是職工檔案的讀取!n");printf("請輸入文件路徑及文件名:");scanf("%s",filepn);/*輸入文件路徑及名稱*/if(fp=fopen(filepn,"r+")=NULL)printf("不能打開文件!n"); i=0;while(!feof(fp) fread(&worki+,sizeof(struct worker),1,fp); number=i-1;/*排序函數(shù)*/void sort()int i,j,n=MAX_NUM,s,v; char temp20; printf("n您選擇的是數(shù)據(jù)排序!n");printf(" *請選擇排序方式*n");printf("t t 1-按編號排序;t t t t 2-按工資排序n"); /*以下可以修改為子菜單方式:1-按編號排序,2-按工資排序*/printf(" *n");printf("請選擇:");scanf("%d",&v);switch(v) case 1: for(i=0;i<=n;i+)for(j=i+1;j<=n;j+)if(workj.ID<worki.ID)strcpy(temp,worki.Birth);strcpy(worki.Birth,workj.Birth);strcpy(workj.Birth,temp);strcpy(temp,worki.Name);strcpy(worki.Name,workj.Name);strcpy(workj.Name,temp);strcpy(temp,worki.Sex);strcpy(worki.Sex,workj.Sex);strcpy(workj.Sex,temp);s=worki.Wage; worki.Wage=workj.Wage; workj.Wage=s;strcpy(temp,worki.Telenum);strcpy(worki.Telenum,workj.Telenum);strcpy(workj.Telenum,temp);strcpy(temp,worki.Department);strcpy(worki.Department,workj.Department);strcpy(workj.Department,temp);strcpy(temp,worki.Job);strcpy(worki.Job,workj.Job);strcpy(workj.Job,temp); s=worki.ID; worki.ID=workj.ID; workj.ID=s; printf(" 新的排序如下:n"); printf("t編號t姓名 t出生年月t電話t 性別t工資t部門t職稱n"); for(i=0;i<n;i+) printf("t%dt%s t%st%st %st%dt%st%sn",worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job);break ;case 2:int k;printf("n您選擇的是按工資排序!n");printf(" *請選擇排序方式*n");printf("t t 1-按工資從高到低排序;t t t t 2-按工資從低到高排序n"); /*以下可以修改為子菜單方式:1-按工資從高到低排序;2-按工資從低到高排序*/printf(" *n");printf("請選擇:");scanf("%d",&k);switch(k) case 1: for(i=0;i<=n;i+)for(j=i+1;j<=n;j+)if(worki.Wage<workj.Wage)strcpy(temp,worki.Birth);strcpy(worki.Birth,workj.Birth);strcpy(workj.Birth,temp);strcpy(temp,worki.Name);strcpy(worki.Name,workj.Name);strcpy(workj.Name,temp);strcpy(temp,worki.Sex);strcpy(worki.Sex,workj.Sex);strcpy(workj.Sex,temp);s=worki.Wage; worki.Wage=workj.Wage; workj.Wage=s;strcpy(temp,worki.Telenum);strcpy(worki.Telenum,workj.Telenum);strcpy(workj.Telenum,temp);strcpy(temp,worki.Department);strcpy(worki.Department,workj.Department);strcpy(workj.Department,temp);strcpy(temp,worki.Job);strcpy(worki.Job,workj.Job);strcpy(workj.Job,temp); s=worki.ID; worki.ID=workj.ID; workj.ID=s; printf(" 新的排序如下:n"); printf("t編號t姓名 t出生年月t電話t 性別t工資t部門t職稱n"); for(i=0;i<n;i+) printf("t%dt%s t%st%st %st%dt%st%sn",worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job);break ;case 2: for(i=0;i<=n;i+)for(j=i+1;j<=n;j+)if(worki.Wage>workj.Wage)strcpy(temp,worki.Birth);strcpy(worki.Birth,workj.Birth);strcpy(workj.Birth,temp);strcpy(temp,worki.Name);strcpy(worki.Name,workj.Name);strcpy(workj.Name,temp);strcpy(temp,worki.Sex);strcpy(worki.Sex,workj.Sex);strcpy(workj.Sex,temp);s=worki.Wage; worki.Wage=workj.Wage; workj.Wage=s;strcpy(temp,worki.Telenum);strcpy(worki.Telenum,workj.Telenum);strcpy(workj.Telenum,temp);strcpy(temp,worki.Department);strcpy(worki.Department,workj.Department);strcpy(workj.Department,temp);strcpy(temp,worki.Job);strcpy(worki.Job,workj.Job);strcpy(workj.Job,temp); s=worki.ID; worki.ID=workj.ID; workj.ID=s; printf(" 新的排序如下:n"); printf("t編號t姓名 t出生年月t電話t 性別t工資t部門t職稱n"); for(i=0;i<n;i+) printf("t%dt%s t%st%st %st%dt%st%sn",worki.ID,worki.Name,worki.Birth,worki.Telenum,worki.Sex,worki.Wage,worki.Department,worki.Job);break ;