|
1.1需求分析 在對學(xué)生成績管理系統(tǒng)進(jìn)行需求分析的過程中,需要確定系統(tǒng)的主要功能,對軟件開發(fā)的主要目的、軟件的使用領(lǐng)域和有關(guān)該軟件開發(fā)的軟硬件環(huán)境進(jìn)行詳細(xì)的分析。 1.1.1 系統(tǒng)概述 學(xué)生成績管理系統(tǒng)主要用于對學(xué)生的學(xué)號、姓名及各項學(xué)科成績進(jìn)行增、刪、改、查等操作。系統(tǒng)給用戶提供了一個簡單的人機(jī)界面,使用戶可以根據(jù)提示輸入操作項,調(diào)用系統(tǒng)提供的管理功能。 1.1.2 系統(tǒng)運行環(huán)境 一、硬件環(huán)境 處理器:Intel Pentium 166 MX或更高 內(nèi)存:32MB 硬盤空間:1GB 顯卡:SVGA顯示適配器 二、軟件環(huán)境 操作系統(tǒng):Windows 98/ME/2000/XP 2.1.3 功能需求描述  . 輸入學(xué)生信息:用戶根據(jù)提示輸入學(xué)生的學(xué)號、姓名、各科成績,并由系統(tǒng)計算總分和平均分,并設(shè)置名次的初始值為0??梢淮涡暂斎攵鄺l學(xué)生記錄。 . 查找學(xué)生信息:按照學(xué)生姓名查找學(xué)生信息,如果存在,則提示用戶找到并輸出查找結(jié)果。 3. 插入學(xué)生信息:插入在指定學(xué)號的記錄前,先查找指定學(xué)號是否存在,若存在,直接插入在此記錄前,若不存在,則插入在所有記錄最后。 . 修改學(xué)生信息:提示用戶輸入要修改的學(xué)生學(xué)號,查找該學(xué)號是否存在,成功則允許修改該學(xué)生的姓名、學(xué)科成績等主要內(nèi)容,并重新計算總分和平均分;失敗,顯示沒找到。 . 刪除學(xué)生信息:提示用戶輸入要刪除的學(xué)生學(xué)號,如在,則刪除,若沒有,則提示相應(yīng)信息。 6. 保存信息至文件: 將所有的學(xué)生成績信息保存到磁盤文件中,以方便用戶管理。 . 讀文件:將磁盤文件中的數(shù)據(jù)讀到內(nèi)存以供用戶進(jìn)行查詢、修改、刪除、添加、排序等操作。 8. 學(xué)生成績排序:根據(jù)學(xué)生成績的總分進(jìn)行降序排列,并將排序結(jié)果顯示給用戶。 . 計算學(xué)生總分和平均分:計算每位學(xué)生的總分和平均分,并計算所有學(xué)生的總分和平均分。 10. 文件備份:將磁盤文件做一個備份文件,以防止數(shù)據(jù)意外丟失。 2.2總體設(shè)計 2.2.1設(shè)計思路 程序設(shè)計一般由兩部分組成:算法和數(shù)據(jù)結(jié)構(gòu),合理地選擇和實現(xiàn)一個數(shù)據(jù)結(jié)構(gòu)和處理這些數(shù)據(jù)結(jié)構(gòu)具有同樣的重要性。在管理程序中,若使用靜態(tài)數(shù)組保存數(shù)據(jù),則會占用連續(xù)的存儲空間。它的缺點是需要預(yù)先估計記錄大小,如果估計得過大,則浪費空間,如果小了,不容易擴(kuò)充。特別是當(dāng)需要動態(tài)變化時,例如插入數(shù)據(jù)和刪除數(shù)據(jù)等操作需要移動數(shù)據(jù),容易出錯。所以我們使用單鏈表結(jié)構(gòu)來管理學(xué)生成績,這樣,不用事先估計學(xué)生人數(shù),方便隨時插入和刪除學(xué)生記錄,且不必移動數(shù)據(jù),實現(xiàn)動態(tài)管理。代價是犧牲一部分空間用來存放表示結(jié)點關(guān)系的指針。當(dāng)然,鏈表的靈活性也帶來了管理的復(fù)雜性。 2.2.2系統(tǒng)模塊結(jié)構(gòu)圖 本程序利用單鏈表存儲結(jié)構(gòu)完成對學(xué)生成績的動態(tài)管理,其基本功能模塊如圖3-1所示。 2.2.3數(shù)據(jù)結(jié)構(gòu)設(shè)計 將一個學(xué)生當(dāng)作一個結(jié)點,這個結(jié)點的類型為結(jié)構(gòu)體,結(jié)構(gòu)體中的域表示學(xué)生的屬性,每個結(jié)點除了存放屬性外,還存放結(jié)點之間的關(guān)系,即存放指向后繼結(jié)點的指針。結(jié)點結(jié)構(gòu)如下: #define N 3 //定義課程門數(shù),可以根據(jù)情況設(shè)定 typedef struct student//定義數(shù)據(jù)結(jié)構(gòu) no[10]; //學(xué)號 char name[20]; //姓名 score[N]; //各門課成績 float sum; //總分 ave;//平均分 int order;//名次 student *next;//指向后繼結(jié)點的指針 STU;//結(jié)構(gòu)體類型名 2.2.4功能模塊設(shè)計 一、main()主函數(shù) 圖3-2 主控函數(shù)執(zhí)行流程 程序采用模塊化設(shè)計,主函數(shù)是程序的入口,主函數(shù)不宜復(fù)雜,功能盡量在各模塊中實現(xiàn)。main()函數(shù)執(zhí)行流程圖如圖3-2所示。 首先聲明一些必要的變量,然后作一無限循環(huán)程序,循環(huán)體為一個開關(guān)語句,該語句的條件值是通過調(diào)用主菜單函數(shù)得到的返回值,根據(jù)該值,調(diào)用相應(yīng)的各功能函數(shù),同時設(shè)置一個斷點,即當(dāng)返回值為一定條件時運行exit()函數(shù)結(jié)束程序,以免造成死循環(huán)。 二、menu_select()主菜單 直接利用輸出函數(shù)printf輸出字符串,在屏幕上顯示一個菜單,并顯示一個提示輸入選項,輸入0-12之間的數(shù)字,將此數(shù)字作為菜單函數(shù)的返回值返回主函數(shù),主函數(shù)根據(jù)這個數(shù)字調(diào)用相應(yīng)的功能函數(shù)。制作簡便,操作簡單,界面如圖3-3所示。 三、輸入記錄模塊 .從鍵盤輸入 輸入學(xué)生信息的同時,創(chuàng)建鏈表。按照提示信息輸入學(xué)號、姓名、三門課程成績,每輸入一個數(shù)就按一下回車鍵,當(dāng)輸入學(xué)號首字符為@時結(jié)束輸入,返回主函數(shù),單鏈表創(chuàng)建完畢。 在生成鏈表時,每次新輸入的結(jié)點放在表頭,這樣最先輸入的結(jié)點存放在最后。 對于數(shù)據(jù)庫管理,為避免數(shù)據(jù)出錯或減少數(shù)據(jù)出錯的概率,應(yīng)考慮數(shù)據(jù)完整性的驗證。該功能由兩個函數(shù)create()和inputs()完成。設(shè)置頭指針為空,申請內(nèi)存空間,如果申請不到,則內(nèi)存空間滿,無法保存數(shù)據(jù),則返回主程序;否則輸入數(shù)據(jù),并進(jìn)行相應(yīng)的校驗(學(xué)號和姓名調(diào)用函數(shù)inputs輸入和校驗),成績就在create()中邊輸入邊驗證,以保證輸入合法數(shù)據(jù)。當(dāng)成績輸入后,計算該生的總分和平均分,并將名次數(shù)據(jù)先置0,待排序后再賦予新值。數(shù)據(jù)輸入后,將其后繼結(jié)點指針指向當(dāng)前頭結(jié)點,新頭指針指向新輸入結(jié)點,這樣新插入結(jié)點總在頭。數(shù)據(jù)輸入結(jié)束后返回鏈表的頭指針到主函數(shù)。 .從文件讀入 按照文件的讀寫要求,先定義一個指向文件的指針,輸入讀入數(shù)據(jù)的磁盤文件名,然后確定文件的打開方式。如果文件打不開,則退出函數(shù),否則選擇一種讀文件方式,從文件頭開始,將記錄讀入內(nèi)存,直到文件尾。文件打開方式和讀入方式的確定要依據(jù)輸出文件的打開方式和寫入方式,以免數(shù)據(jù)讀入錯誤。如果輸出文件是二進(jìn)制文件,塊寫操作,讀入也應(yīng)設(shè)置為二進(jìn)制打開方式,塊讀取方式。每讀入一條記錄,都要做好指針鏈接關(guān)系,本模塊將新結(jié)點鏈接到當(dāng)前鏈表的尾部,鏈表的順序和文件保存的順序一致。 四、更新記錄模塊 .查詢記錄 按照姓名查找結(jié)點,從頭結(jié)點開始順序查找,成功顯示記錄信息,失敗,顯示沒找到。姓名是字符串,比較功能利用字符串比較函數(shù)strcmp()實現(xiàn)。 .修改記錄 輸入要進(jìn)行修改的學(xué)生學(xué)號,從頭結(jié)點開始順序查找該學(xué)號是否存在,成功則允許修改該學(xué)生的姓名、學(xué)科成績等主要內(nèi)容,并重新計算總分和平均分;失敗,顯示沒找到。 .刪除記錄 刪除指定學(xué)號的學(xué)生記錄。首先輸入要刪除結(jié)點的學(xué)號,輸入后根據(jù)學(xué)號順序查找結(jié)點,如果沒找到,則輸出沒找到信息;;否則,顯示找到的結(jié)點信息,按任意鍵后顯示已刪除信息。注意刪除結(jié)點時的操作,如果該結(jié)點是首結(jié)點,則要修改頭指針,如圖3-4所示;否則,將該結(jié)點的前趨指針的后繼指向其后繼結(jié)點,如圖3-5所示,然后釋放該結(jié)點。 4.插入記錄 插入結(jié)點需要輸入插入位置和新結(jié)點信息。輸入某個結(jié)點的學(xué)號,新結(jié)點將插入在這個指定結(jié)點之前。申請空間得到指針info,輸入新結(jié)點信息,存放到新申請的空間info中。設(shè)鏈表頭指針為h,p為指定結(jié)點的指針,q為p的前趨指針。從頭結(jié)點開始循環(huán)移動指針p查找指定結(jié)點,查找和插入時分以下幾種情況處理: ⑴ 指針p為空,如果p等于頭指針h,說明鏈表為空,則新結(jié)點即為頭結(jié)點,修改指針h=info。否則,說明表中沒有指定結(jié)點,則新結(jié)點插入在表尾部,此時q所指結(jié)點是最后一個結(jié)點,所以修改指針q-next=info,如圖3-6所示。 ⑵ 指針p不為空,如果p等于h,說明新結(jié)點插入在當(dāng)前第一個結(jié)點之前,為新的頭結(jié)點,修改指針info-next=p,h=info,如圖3-7所示。否則,說明新結(jié)點的位置應(yīng)在p和q兩個結(jié)點之間,修改指針 五、統(tǒng)計紀(jì)錄模塊 .學(xué)生成績計算 從頭指針開始,每讀一條記錄,將該生的總分累加,并統(tǒng)計記錄條數(shù),當(dāng)所有數(shù)據(jù)處理完畢,求出平均分,最后輸出結(jié)果為所有學(xué)生的總分和平均分。 .學(xué)生成績排序 對于學(xué)生成績管理,一個很重要的運算是將學(xué)生按照分?jǐn)?shù)由高到低排名,本模塊實現(xiàn)按照總分排序功能。 排序算法有很多,對于確定的數(shù)據(jù)結(jié)構(gòu),應(yīng)選用一種合適的算法。由于學(xué)生信息采用的是單鏈表存儲結(jié)構(gòu),所以選用直接插入算法較為簡單。直接插入算法的基本方法是:每步將一個待排序的記錄按其排序碼值的大小插到前面已經(jīng)排序好的表中,直到全部插入為止?;谶@樣的方法首先將鏈表的頭結(jié)點看作是已排好序的結(jié)點,然后取下一個結(jié)點作為待排序的結(jié)點,插入到已排好序的表中。由于單鏈表的特性,所以具體的思路如下: ⑴ 先將原表頭結(jié)點作為新排好序表的頭結(jié)點h,原表下一個結(jié)點作為原表頭結(jié)點h1,設(shè)原表如圖3-9所示,表中只列出總分?jǐn)?shù)據(jù)。 ⑵ 原表頭結(jié)點為待排序結(jié)點,將其總分與新表結(jié)點的總分進(jìn)行比較,如果待排序結(jié)點總分大,則插在新表的頭,否則插入在其后,原表頭結(jié)點后移一位,如圖3-10所示。 ⑶ 重復(fù)第二步,則將原表頭結(jié)點的總分和新表結(jié)點的總分進(jìn)行比較,如果待排序結(jié)點總分小,則移動新表指針,直到找到合適的位置將其插入,直到原表為空,所有結(jié)點排序完畢,如圖3-11所示。 六、輸出記錄模塊 .文件備份模塊 為了保存數(shù)據(jù),防止意外發(fā)生,為數(shù)據(jù)做備份是很有必要的。 本模塊是將文件讀寫功能結(jié)合到一起的應(yīng)用。先輸入源文件名,再輸入目標(biāo)文件名,然后利用文件讀寫函數(shù)將源文件中的信息寫到目標(biāo)文件中。 .學(xué)生信息保存至文件 將學(xué)生信息保存到指定文件中。按照文件的讀寫要求,先定義一個指向文件的指針,輸入要保存的磁盤文件名,如果輸入的是絕對路徑,則文件保存到指定位置;如果只給文件名,則文件保存在VC6.0默認(rèn)的路徑下。然后確定文件的打開方式,打開文件。如果文件打不開,則退出程序,否則選擇一種寫文件方式,從鏈表的頭指針開始,順序?qū)⒂涗泴懭胛募?,直到所有記錄寫完,?biāo)志就是移動后指針為空。 .顯示所有學(xué)生信息---輸出至屏幕 學(xué)生成績表建立好后,更頻繁的操作是顯示和查找記錄,本模塊實現(xiàn)顯示所有鏈表數(shù)據(jù)功能。輸出界面如圖3-12所示。 由于單鏈表只能采取順序訪問的方法,所以定義一個指向結(jié)點的臨時變量p,初值為單鏈表的頭指針,輸出指針?biāo)赣涗浀臄?shù)據(jù)后,將指針后移一個記錄,直到p指針值為空,則所有記錄輸出完畢。設(shè)計本模塊時注意輸出格式以二維表格的形式輸出,直觀漂亮。輸出的第一列為記錄號。注意調(diào)整格式,對齊表格線。 .3詳細(xì)設(shè)計 .3.1程序預(yù)處理 包括加載頭文件,定義結(jié)構(gòu)體、常量和變量,并對它們進(jìn)行初始化。 #include stdio.h //I/O函數(shù) #include stdlib.h //標(biāo)準(zhǔn)庫函數(shù) #include string.h //字符串函數(shù) #include ctype.h //字符操作函數(shù) #include conio.h//控制臺輸入輸出函數(shù) #include malloc.h //動態(tài)地址分配函數(shù) #include memory.h //內(nèi)存操作函數(shù) #define N 3 //定義課程門數(shù),可以根據(jù)情況設(shè)定 typedef struct student//定義數(shù)據(jù)結(jié)構(gòu) no[10]; //學(xué)號 char name[20]; //姓名 score[N]; //各門課成績 float sum; //總分 ave;//平均分 int order;//名次 student *next;//指向后繼結(jié)點的指針 STU;//結(jié)構(gòu)體類型名 /**********以下是函數(shù)原型***********/ STU *init(); //初始化函數(shù) STU *create(); //創(chuàng)建鏈表 print(STU *h); //顯示所有記錄 void search(STU *h);//查找記錄 STU *insert(STU *h); //插入記錄 STU *modify(STU *h); //修改記錄 *delete(STU *h); //刪除記錄 void save(STU *h); //記錄保存為文件 STU *load(); //從文件中讀記錄 void compute(STU *h); //計算總分和平均分 STU *sort(STU *h);//排序 void copy();//文件備份 inputs(char *prompt,char *s,int count); //輸入字符串,并進(jìn)行長度驗證 int menu_select(); //主菜單函數(shù) .3.2主函數(shù)main() 實現(xiàn)對整個程序的運行控制,以及相關(guān)功能模塊的調(diào)用。 int main() *head; //鏈表定義頭指針 =init();//初始化鏈表 (cls); //清屏 for (;;) //無限循環(huán) (menu_select()) 0:head=init();break; //執(zhí)行初始化 1:head=create();break; //輸入記錄創(chuàng)建鏈表 case 2:print(head);break; //顯示所有記錄 3:search(head);break;//查找記錄 4:head=insert(head);break;//插入記錄 case 5:head=modify(head);break;//修改記錄 case 6: head=delete (head);break;//刪除記錄 case 7:save(head);break;//保存文件 case 8:head=load();break;//讀文件 9:compute(head);break;//計算總分和平均分 10:head=sort(head);break;//排序 return 0; 11:copy();break;//文件備份 case 12:exit(0);//結(jié)束程序 .3.3menu_select()主菜單 用戶進(jìn)入通訊錄管理系統(tǒng)時,需要顯示主菜單,提示用戶進(jìn)行選擇,完成相應(yīng)任務(wù)。此代碼被main()函數(shù)調(diào)用。 /******************************************** 函數(shù)功能:顯示主菜單,進(jìn)行功能選擇 入口參數(shù):無 出口:返回用戶的選項 調(diào)用方式:menu_select() ********************************************/ int menu_select() s[80]; int c; (按任意鍵繼續(xù)); getch(); (cls);//清屏 (*************學(xué)生成績管理系統(tǒng)菜單***************); printf( 0.初始化); ( 1.輸入記錄); ( 2.顯示全部記錄); printf( 3.查找記錄); printf( 4.插入記錄); printf( 5.修改記錄); printf( 6.刪除記錄); printf( 7.保存文件); printf( 8.讀文件); ( 9.計算總分和平均分); printf( 10.按總分排序); printf( 11.文件備份); ( 12.退出); (*****************************************); do (輸入你的選擇(0-12):); scanf(%s,s); =atoi(s);//將數(shù)字字符串轉(zhuǎn)換為數(shù)值 while (c<0||c12); return c; .3.4初始化 /******************************************** 函數(shù)功能:初始化鏈表 入口參數(shù):無 出口:返回一個鏈表空指針 調(diào)用方式: init() ********************************************/ STU *init() NULL; .3.5輸入記錄模塊 一、從鍵盤輸入 按照提示信息輸入學(xué)號、姓名、三門課程成績,并計算出總分和平均分,同時,創(chuàng)建鏈表。 /******************************************************* 函數(shù)功能:輸入字符串,并進(jìn)行長度驗證 入口參數(shù):prompt:提示信息,s:待驗證字符串,count:長度 出口:無 調(diào)用方式: inputs(“輸入姓名:”,info-name,20); *******************************************************/ void inputs(char *prompt,char *s,int count) p[255];; do (prompt);//顯示提示信息 scanf(“%s”,p);;//輸入字符串 (strlen(p)count) printf(“l(fā)ong!”);//進(jìn)行長度驗證,超過count值重新輸入 while(strlen(p)count);; (s,p);//將輸入的字符串拷貝到字符串s中 /********************** 函數(shù)功能:創(chuàng)建鏈表 入口參數(shù):無 出口:返回鏈表頭指針 調(diào)用方式:create(); **********************/ STU *create() i; float s; *h=NULL,*info; (STU *)malloc(sizeof(STU));//申請空間 (!info)//若指針info為空 (“out of memory”);//提示內(nèi)存溢出 return NULL; //返回空指針 (“輸入學(xué)號:”,info-no,10);//輸入學(xué)號并檢驗 (info-no[0]==’@’) break;//如果學(xué)號首字符為@,結(jié)束輸入 inputs(“輸入姓名:”,info-name,20); //輸入姓名并檢驗 printf(“請輸入%d門課程成績”,N);//提示開始輸入成績 s=0;//計算每個學(xué)生的總分,初值為0 for(i=0;i<N;i ) do (“課程%d:”,i 1);//提示輸入第幾門課程 scanf(“%f”,&info-score[i]);//輸入成績 if(info-score[i]100||info-score[i]<0) printf(“成績超出指定范圍!”); while(info-score[i]100||info-score[i]<0); s =info-score[i];//累加各門成績 sum=s;//將總分保存 info-ave=s/N;//求平均分 info-order=0;;//未排序前此值為0 info-next=h;//將頭結(jié)點作為新輸入結(jié)點的后繼結(jié)點 h=info;//新輸入結(jié)點為新的頭結(jié)點 h;//返回頭指針 二、從文件讀入數(shù)據(jù) /******************************************************* 函數(shù)功能:從文件讀數(shù)據(jù),并把讀入的數(shù)據(jù)鏈入鏈表 入口參數(shù):無 出口:返回鏈表頭指針 調(diào)用方式:load(); *******************************************************/ STU *load() *p,*q,*h=NULL; FILE *fp; char infile[50]; (請輸入文件名,例如:c:f1 e.dat:);//提示文件名格式信息 scanf(%s,infile); ((fp=fopen(infile,rb))==NULL) (讀文件); =(STU *)malloc(sizeof(STU)); if(!p) h=p; (!feof(fp)) (1!=fread(p,sizeof(STU),1,fp)); (不能打開文件!); exit(1); (內(nèi)存溢出!); return h; (內(nèi)存溢出!); h; q=p; p=p-next; next=NULL;; fclose(fp); (成功讀取文件!); return h; .3.6更新記錄模塊 一、查找記錄 從頭結(jié)點開始順序查找,查找指定姓名的記錄。 /****************************** 函數(shù)功能:按照姓名查找記錄 入口參數(shù):h:鏈表頭指針 出口:無 調(diào)用方式:search(head); ******************************/ void search(STU *h) *p;//移動指針 s[20];//存放姓名的字符數(shù)組 system(cls);//清屏 (請輸入要查找的姓名:); scanf(%s,s);//輸入姓名 =h; (strcmp(p-name,s)&&p!=NULL) =p-next ;//移動指針,指向下一結(jié)點 (p==NULL) (沒有姓名為%s的學(xué)生!,s); (**********************查找結(jié)果******************); (學(xué)號姓名課程1課程2課程3總分平均分名次); (--------------------------------------------------------------------------); printf(%s%s%.1f%.1f%.1f%.1f%.1f%d,p-no, name,p-score[0],p-score[1],p-score[2],p-sum,p-ave,p-order); (--------------------------------------------------------------------------); 二、插入記錄 在指定學(xué)號的學(xué)生前插入一條記錄。若指定學(xué)號不存在且學(xué)生表為空表,則直接插入此學(xué)生信息為頭結(jié)點,若學(xué)生表不為空表,則在表尾插入。若指定學(xué)號存在,且為頭結(jié)點,則新輸入的學(xué)生信息作為新的頭結(jié)點插入在指定學(xué)號前,否則,作為中間結(jié)點直接插入到指定學(xué)號前。 /****************************** 函數(shù)功能:插入記錄 入口參數(shù):h:鏈表頭指針 出口:返回鏈表頭指針 調(diào)用方式:insert(head); ******************************/ STU *insert(STU *h) *p,*q,*info;//p指向插入位置,q是其前趨,info指新插入記錄 char s[10];//保存插入點位置的學(xué)號 float s1;int i;(在哪個學(xué)號前插入?);; scanf(%s,s);;//輸入插入點學(xué)號 printf(請輸入新的記錄:); =(STU *)malloc(sizeof(STU));//申請空間 if(!info) (out of memory);//提示內(nèi)存溢出 NULL; //返回空指針 (輸入學(xué)號:,info-no,10);//輸入學(xué)號并檢驗 inputs(輸入姓名:,info-name,20); //輸入姓名并檢驗=0;//計算每個學(xué)生的總分,初值為0 for(i=0;i<N;i ) (課程%d:,i 1);//提示輸入第幾門課程 scanf(%f,&info-score[i]);//輸入成績 if(info-score[i]100||info-score[i]<0) printf(成績超出指定范圍!); while(info-score[i]100||info-score[i]<0); s1 =info-score[i];//累加各門成績 sum=s1;//將總分保存 info-ave=s1/N;//求平均分 info-order=0;//名次賦為0 next=NULL;//設(shè)后繼指針為空 p=h; q=h; (p!=NULL&&strcmp(p-no,s)) //查找插入位置 (p==NULL) //如果p指針為空,說明沒有指定結(jié)點 else (p==h) else =p; p=p-next; (p==h)//同時p等于h,說明鏈表為空 else next=info;//p不為空,但p不等于h,將新結(jié)點插在表尾 h=info;//新記錄則為頭結(jié)點 next=p;//如果p等于h,則新結(jié)點插入在第一個結(jié)點之前 h=info;//新結(jié)點為頭結(jié)點 next=info;//新結(jié)點作為q的后繼結(jié)點 (成功插入!); return h; 三、修改記錄 /******************************** 函數(shù)功能:修改指定學(xué)號的學(xué)生信息 入口參數(shù):h:鏈表頭指針 出口:返回鏈表頭指針 調(diào)用方式:modify(head); ********************************/ STU *modify(STU *h) *p;//p為查找到要修改的結(jié)點指針 char s[10];//存放學(xué)號 int i; float s1; system(cls);//清屏 (請輸入要修改的學(xué)生學(xué)號:); scanf(%s,s); p=h; (p!=NULL&&strcmp(p-no,s)) //查找 =p-next; (p==NULL) (找到該學(xué)生!學(xué)生信息見下列); (學(xué)號姓名課程1課程2課程3總分平均分名次); printf(--------------------------------------------------------------------------); printf(%s%s%.1f%.1f%.1f%.1f%.1f%d,p-no,p-name, score[0],p-score[1],p-score[2],p-sum,p-ave,p-order); (--------------------------------------------------------------------------); (沒有該學(xué)生!); printf(請輸入修改信息:); (輸入學(xué)號:,p-no,10);//輸入學(xué)號并檢驗 inputs(輸入姓名:,p-name,20); //輸入姓名并檢驗 printf(請輸入%d門課程成績,N);//提示開始輸入成績 =0;//計算每個學(xué)生的總分,初值為0 for(i=0;i<N;i ) (課程%d:,i 1);//提示輸入第幾門課程 scanf(%f,&p-score[i]);//輸入成績 if(p-score[i]100||p-score[i]<0) printf(成績超出指定范圍!); while(p-score[i]100||p-score[i]<0); =p-score[i];//累加各門成績 return h; sum=s1;//將總分保存 p-ave=s1/N;//求平均分 printf(修改成功!); 四、刪除記錄 /******************************** 函數(shù)功能:刪除指定學(xué)號的記錄 入口參數(shù):h:鏈表頭指針 出口:返回鏈表頭指針 調(diào)用方式:delet(head); ********************************/ STU *delet(STU *h) *p,*q;//p為查找到要刪除的結(jié)點指針,q為其前趨指針 char s[10];//存放學(xué)號 char ch; (cls);//清屏 (請輸入要刪除的學(xué)生學(xué)號:); scanf(%s,s); =p=h; (p!=NULL&&strcmp(p-no,s)) //查找 =p; p=p-next; (p==NULL) (找到該學(xué)生!學(xué)生信息見下列); (學(xué)號姓名課程1課程2課程3總分平均分名次); printf(--------------------------------------------------------------------------); printf(%s%s%.1f%.1f%.1f%.1f%.1f%d,p-no,p-name, score[0],p-score[1],p-score[2],p-sum,p-ave,p-order); (--------------------------------------------------------------------------); printf(確定要刪除這條記錄嗎?(Y/N):); return h; (沒有該學(xué)生!); =getch();//此處一定要用getch函數(shù)輸入,其它函數(shù)均不可以 if(ch=='Y' || ch=='y') (p==h)//若被刪結(jié)點是頭結(jié)點 else next=p-next;//不是頭結(jié)點,將p的后繼結(jié)點作為q的后繼結(jié)點 h=p-next;//修改頭指針指向下一條記錄 (p); (刪除成功!); .3.7統(tǒng)計記錄模塊 一、計算總分和平均分 /******************************** 函數(shù)功能:計算總分和平均分 入口參數(shù):h:鏈表頭指針 出口:無 調(diào)用方式:compute(head); ********************************/ void compute(STU *h) *p;//定義移動指針 i=0;//保存記錄條數(shù),初值為0 float s=0;//總分初值為0 float ave=0;//平均分初值為0 p=h;//從頭指針開始 while(p!=NULL) ave=s/i; (所有學(xué)生的總分為:%.2f,平均分為:%.2f,s,ave); =p-sum;//累加總分 i ; p=p-next; 二、按總分排序 直接插入排序。 /******************************** 函數(shù)功能:按總分排序 入口參數(shù):h:鏈表頭指針 出口:返回鏈表頭指針 調(diào)用方式:sort(head); ********************************/ STU *sort(STU *h) i=0;//保存名次 *p,*q,*t,*h1;//定義臨時指針 =h-next;//將原表頭指針?biāo)傅南乱粋€結(jié)點作為頭指針 h-next=NULL;//第一個結(jié)點為新表的頭結(jié)點 while(h1!=NULL)//當(dāng)原表不為空時,進(jìn)行排序 =h1;//取原表的頭結(jié)點 =h1-next;//原表頭結(jié)點指針后移 p=h;//設(shè)定移動指針p,從頭指針開始 =h;//設(shè)定移動指針q作為p的前趨,初值為頭指針 while(p!=NULL&&t-sum<p-sum)//進(jìn)行總分比較 (p==q)//p==q,說明待排序點值大,應(yīng)排在首位 //待排序點應(yīng)插入在中間某個位置q和p之間,如果p為空則是尾部 next=p;//待排序點的后繼為p q-next=t;//q的后繼是t t-next=p;//待排序點的后繼為p h=t;//新頭結(jié)點為待排序點 =p;//待排序點值小,則新表指針后移 p=p-next; =h;//已排序好的頭指針賦給p,準(zhǔn)備填寫名次 (p!=NULL) (排序成功!); return h; ;//結(jié)點序號 p-order=i;//將名次賦值 p=p-next;//指針后移 .3.8輸出記錄模塊 一、輸出記錄至屏幕 顯示所有的學(xué)生信息。 /******************************** 函數(shù)功能:輸出全部記錄 入口參數(shù):h:鏈表頭指針 出口:無 調(diào)用方式:print(head); ********************************/ void print(STU *h) i=0;//統(tǒng)計記錄個數(shù) STU *p;//移動指針 system(cls);;//清屏 p=h; (****************學(xué)生信息****************************); printf(序號學(xué)號姓名課程1課程2課程3總分平均分名次); printf(-------------------------------------------------------------------------------); while(p!=NULL) ; (%d%s%s%.1f%.1f%.1f%.1f%.1f%d,i,p-no, name,p-score[0],p-score[1],p-score[2],p-sum,p-ave,p-order); (-------------------------------------------------------------------------------); =p-next;; 二、保存數(shù)據(jù)至文件 /******************************** 函數(shù)功能:保存數(shù)據(jù)到文件 入口參數(shù):h:鏈表頭指針 出口:無 調(diào)用方式:save(head); ********************************/ void save(STU *h) *fp;//定義指向文件的指針 STU *p;//定義移動指針 char outfile[50];//文件名 (請輸入文件名,例如:c:f1 e.dat:);//提示文件名格式信息 scanf(%s,outfile); ((fp=fopen(outfile,wb))==NULL)
信息發(fā)布:廣州名易軟件有限公司 http://www.jetlc.com
|