最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

《學(xué)生信息管理系統(tǒng)》案例設(shè)計(jì)過(guò)程

2023-08-21 09:28 作者:Iam107  | 我要投稿

適用于2022級(jí)軟工同學(xué)

說(shuō)明:

該文檔針對(duì)《程序設(shè)計(jì)實(shí)踐》課程的大作業(yè)-****系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)過(guò)程中思路的搭建以及出現(xiàn)的問(wèn)題進(jìn)行闡述

為了讓大家更好地理解整個(gè)系統(tǒng)的設(shè)計(jì)和開(kāi)發(fā)過(guò)程,這里擬定有層次地闡述,以“學(xué)生成績(jī)管理系統(tǒng)”為例,大家可以根據(jù)自己的情況去有選擇地學(xué)習(xí)。

注意:這里也是為啥我不建議有同學(xué)自選題目說(shuō)要做學(xué)生信息管理系統(tǒng)的原因,因?yàn)橄M隳軌蜃约邯?dú)立地完成一個(gè)相對(duì)獨(dú)立的系統(tǒng);

1 思路整理

基礎(chǔ)設(shè)計(jì):

問(wèn)題1:你設(shè)計(jì)的系統(tǒng),是否利用“文件”來(lái)存儲(chǔ)相關(guān)數(shù)據(jù)?

答:若不用,那系統(tǒng)就沒(méi)有辦法將數(shù)據(jù)存入文件中,只是在內(nèi)存中,演示的話,只能運(yùn)行程序,然后一條條地錄入數(shù)據(jù)并演示各種功能,當(dāng)關(guān)閉程序時(shí),你之前錄入的數(shù)據(jù),都沒(méi)有了,因?yàn)?,你沒(méi)有將相關(guān)的數(shù)據(jù)存入到文件,即磁盤中!我希望你能完成帶“文件”存儲(chǔ)功能的系統(tǒng),這樣你會(huì)對(duì)這學(xué)期的知識(shí)點(diǎn)更加全面地理解!

當(dāng)然,根據(jù)你自己的情況來(lái)最好!若你非不用,那就好好地在功能上多考慮一些,也不是不行!

問(wèn)題2:學(xué)生信息管理,你是否打算就是單純的學(xué)生信息管理,不涉及到成績(jī)管理以及課程信息管理等功能呢?還是說(shuō)都涉及到呢?

答:這里你有幾個(gè)方案選擇:

方案1:就做學(xué)生信息管理(比如學(xué)號(hào)、姓名、性別、籍貫、政治面貌、專業(yè)、所屬學(xué)院等等),用一個(gè)文件存儲(chǔ)上述信息,比如這個(gè)文件名為student即可。

方案2:同方案1類似,在上述信息的基礎(chǔ)上,多幾個(gè)成績(jī)信息,比如(比如學(xué)號(hào)、姓名、性別、籍貫、政治面貌、專業(yè)、所屬學(xué)院,語(yǔ)文成績(jī)、數(shù)學(xué)成績(jī)、外語(yǔ)成績(jī)),其實(shí)也算是學(xué)生信息管理系統(tǒng),也可以看成學(xué)生成績(jī)管理系統(tǒng),因?yàn)橐泊_實(shí)是管理里一部分成績(jī)的功能。但其不足之處在于:課程就是語(yǔ)文、數(shù)學(xué)和外語(yǔ),當(dāng)系統(tǒng)做好后,若想自由增加,就很難,必須修改修改很多相應(yīng)的代碼;當(dāng)然,也是用一個(gè)文件(文件名為student)就可以存儲(chǔ)上述信息。

其實(shí)方案和方案2基本上是一樣的,可以視為一回事呀!

方案3:其實(shí)這里就是我們?cè)谌蝿?wù)書(shū)中提到的擴(kuò)展功能啦,就除了單純的學(xué)生信息管理之外,也擴(kuò)展了選課功能以及課程信息管理。

這個(gè)選擇相對(duì)功能完善:即學(xué)生成績(jī)管理系統(tǒng),能夠管理學(xué)生信息+課程信息+課程對(duì)應(yīng)成績(jī) 三方面的數(shù)據(jù);其對(duì)應(yīng)的關(guān)系呢,圖示如下;(這個(gè)圖呢,實(shí)際上,是將來(lái)數(shù)據(jù)庫(kù)原理課程中的ER實(shí)體-關(guān)系圖)

注意:這里并非讓你學(xué)習(xí)這個(gè),而是讓你知道,這個(gè)ER圖,將來(lái)要轉(zhuǎn)換為3個(gè)數(shù)據(jù)庫(kù)的表,對(duì)應(yīng)于我們現(xiàn)在實(shí)現(xiàn)學(xué)生選課系統(tǒng)的三個(gè)存儲(chǔ)數(shù)據(jù)的文件-學(xué)生文件(存儲(chǔ)學(xué)生信息)、課程文件(存課程的相關(guān)信息)、選課文件(存學(xué)號(hào)、課程號(hào)、該課程成績(jī)等信息)

此時(shí):至少需要3個(gè)文件(例如student文件、course文件、score文件)來(lái)存儲(chǔ)上述信息呀!

問(wèn)題3:系統(tǒng)采用的數(shù)據(jù)結(jié)構(gòu)是什么?即打算用單鏈表來(lái)存儲(chǔ)并操作相關(guān)數(shù)據(jù)?還是利用上學(xué)期的結(jié)構(gòu)體數(shù)組來(lái)操作呢呢?或者是說(shuō):有些時(shí)候用單鏈表,到排序的時(shí)候,用鏈表實(shí)現(xiàn)起來(lái)不爽,再考慮用結(jié)構(gòu)體數(shù)組來(lái)實(shí)現(xiàn)?

答:這里我建議大家可以根據(jù)自己的能力進(jìn)行選擇,實(shí)際上,用我們這學(xué)期的鏈表最好,這樣可以為數(shù)據(jù)結(jié)構(gòu)課程打下基礎(chǔ),當(dāng)然,你也可以都用(即有單鏈表了,也用了一些結(jié)構(gòu)體數(shù)組),甚至各實(shí)現(xiàn)一個(gè)版本,那就更不錯(cuò),鍛煉了自己。

2 初步實(shí)現(xiàn)

這里,算是個(gè)引入,其實(shí)我們?cè)谡n堂上也這樣講了,但還是擔(dān)心有的孩子沒(méi)有聽(tīng)課,連最基本的啟動(dòng)都不會(huì)。所以,我先以一個(gè)沒(méi)有涉及文件功能+單鏈表的一個(gè)簡(jiǎn)單的學(xué)生成績(jī)管理系統(tǒng)為例(上課講過(guò)的,教材P283第11-10 例),一步一步帶著你嘗試完成一個(gè)框架!

那有同學(xué)會(huì)問(wèn),那沒(méi)有文件,后面加文件容易不?當(dāng)然容易,一步一步來(lái)吧啊!

2.1 搭建“學(xué)生信息管理系統(tǒng)”的框架

2.1.1 結(jié)構(gòu)體類型的定義

定義學(xué)生的結(jié)構(gòu)體類型(根據(jù)自己想要保存的學(xué)生那些信息來(lái)定義結(jié)構(gòu)體中的成員)

你要根據(jù)你自己實(shí)現(xiàn)系統(tǒng)的功能來(lái)定義該結(jié)構(gòu)體呀,當(dāng)然,你如果采用了方案3

struct stud_node{ ? int num; ? char name[20]; ? int score; ? struct stud_node *next; };

因?yàn)槲覀兿M幸粋€(gè)類似于菜單的界面,這里直接采用例11-10的循環(huán)框架,為了讓大家學(xué)會(huì)逐步地?cái)U(kuò)大自己系統(tǒng)的功能,這里我盡可能地一步一步來(lái)闡述。

比如我想實(shí)現(xiàn)的系統(tǒng)功能模塊包括:(學(xué)生信息的錄入模塊、信息修改模塊、信息刪除模塊、信息瀏覽模塊)即增加,刪除,修改以及遍歷功能。注意這里并沒(méi)有涉及 ‘信息查詢模塊“,將來(lái)有賴于大家的進(jìn)一步實(shí)現(xiàn)呀!

你想一下:我們寫程序的時(shí)候,不可能一口氣將所有功能模塊(即對(duì)應(yīng)的函數(shù))都實(shí)現(xiàn)出來(lái),但是我們可以先進(jìn)行規(guī)劃呀?。ㄒ?guī)劃系統(tǒng)初步有哪些功能模塊、每個(gè)函數(shù)的名字、參數(shù)等)

2.1.2 功能模塊的劃分以及定義

當(dāng)你初步規(guī)劃功能模塊后,通常建議呢,用圖的形式展現(xiàn)出來(lái)!勝過(guò)千言萬(wàn)語(yǔ)!

問(wèn):那要是初步規(guī)劃后,后面還需要加,咋辦呢?很簡(jiǎn)單呀,再加上就好了呀!還得表?yè)P(yáng)呢!這就叫不斷迭代呀!

以例11-1為案例,假如我們當(dāng)初就想到了學(xué)生信息的錄入模塊、信息修改模塊、信息刪除模塊、信息瀏覽模塊;那就畫一個(gè)圖展示一下唄!

那接下來(lái),對(duì)上述功能模塊分別給出對(duì)應(yīng)的函數(shù)名以及參數(shù)定義吧

struct stud_node * Create_Stu_Doc(); ?/* 新建鏈表 */ struct stud_node * InsertDoc(struct stud_node * head, struct stud_node *stud); /* 插入 */ struct stud_node * updateDoc(struct stud_node * head, int num); /*修改功能 ? 這個(gè)例11-10中沒(méi)有*/ struct stud_node * DeleteDoc(struct stud_node * head, int num); ?/* 刪除 */ void Print_Stu_Doc(struct stud_node * head); ?/* 遍歷 */

當(dāng)然,這些名稱包括對(duì)應(yīng)參數(shù),都是可以根據(jù)功能來(lái)改變的!比如說(shuō),第三個(gè)功能,信息刪除功能的第二個(gè)參數(shù)是num,是表示當(dāng)你在主函數(shù)中輸入要?jiǎng)h除的學(xué)號(hào)時(shí),調(diào)用該DeleteDoc函數(shù),那我們?nèi)绻窍脒@樣修改:

情形1:老師,我不想在主函數(shù)中錄輸入要?jiǎng)h除的學(xué)號(hào),能不能在該函數(shù)的肚子里,讓用戶輸入要?jiǎng)h號(hào)的學(xué)號(hào)對(duì)應(yīng)的學(xué)生,行不行?當(dāng)然可以了,就把對(duì)應(yīng)的代碼移動(dòng)到該函數(shù)的肚子里,當(dāng)然,對(duì)應(yīng)的函數(shù)的參數(shù)也需要修改呀,比如改為struct stud_node * DeleteDoc(struct stud_node * head)

情形2:老師,我不想按照學(xué)號(hào)進(jìn)行刪除,我能否按照學(xué)生的姓名進(jìn)行刪除?當(dāng)然可以了,當(dāng)然,這樣有個(gè)缺點(diǎn)就是,學(xué)生的名字不能有重復(fù)的名字,要不然就得進(jìn)一步考慮萬(wàn)一有重名的時(shí)候咋辦?那如何修改函數(shù)的參數(shù)呢?

這些都是根據(jù)你自己定義的工作流程來(lái)決定的!

當(dāng)定義好這些函數(shù)的名字和參數(shù)之后,那這些函數(shù)還沒(méi)有寫出來(lái),咋辦?沒(méi)關(guān)系,可以寫成空函數(shù),即肚子里啥都不實(shí)現(xiàn),空起來(lái),可以寫上一條相應(yīng)的輸出語(yǔ)句,表明這個(gè)函數(shù)的功能就行,等后期一步一步地實(shí)現(xiàn)!

那來(lái)吧!

先把主函數(shù)寫上,觀察一下,一個(gè)主函數(shù)+4個(gè)用戶自定義函數(shù)

注意一下,我把主函數(shù)中的一些需要錄入輸入后才能調(diào)用對(duì)應(yīng)函數(shù)的代碼暫時(shí)注釋掉,為了更好地演示主函數(shù)中菜單調(diào)用每個(gè)函數(shù)的效果!

#include<stdio.h> #include<stdlib.h> #include<string.h> struct stud_node{ ? ?int num; ? ?char name[20]; ? ?int score; ? ?struct stud_node *next; }; struct stud_node * Create_Stu_Doc(); ?/* 新建鏈表 */ struct stud_node * InsertDoc(struct stud_node * head, struct stud_node *stud); /* 插入 */ struct stud_node * updateDoc(struct stud_node * head, int num); /* 修改 */ struct stud_node * DeleteDoc(struct stud_node * head, int num); ?/* 刪除 */ void Print_Stu_Doc(struct stud_node * head); ?/* 遍歷 */ int main(void) { ? ?struct stud_node *head, *p; ? ?int choice, num, score; ? ?char name[20]; ? ?int size = sizeof(struct stud_node); ? ?do{ ? ? ? ?printf("1:Create 2:Insert 3:update 4:delete 5:browse 0:Exit\n"); ? ? ? ?scanf("%d", &choice); ? ? ? ?switch(choice){ ? ? ? ? ? ?case 1: ? ? ? ? ? ? ? ?head = Create_Stu_Doc(); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 2: ? ? ? ? ? ? ? ?/* ? ? ? ? ? ? ? ?printf("Input num,name and score:\n"); ? ? ? ? ? ? ? ?scanf("%d%s%d", &num,name, &score); ? ? ? ? ? ? ? ?p = (struct stud_node *) malloc(size); ? ? ? ? ? ? ? ?p->num = num; ? ? ? ? ? ? ? ?strcpy(p->name, name); ? ? ? ? ? ? ? ?p->score = score; ? ? ? ? ? ? ? ?*/ ? ? ? ? ? ? ? ?head = InsertDoc(head, p); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 3: ? ? ? ? ? ? ? ?scanf("%d", &num); ? ? ? ? ? ? ? ?head = updateDoc(head, num); ? ? ? ? ? ? ? ? ?break; ? ? ? ? ? ? ? ? ? ? ? ? ? ?case 4: ? ? ? ? ? ? ? ?printf("Input num:\n"); ? ? ? ? ? ? ? ?scanf("%d", &num); ? ? ? ? ? ? ? ?head = DeleteDoc(head, num); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 5: ? ? ? ? ? ? ? ?Print_Stu_Doc(head); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 0: ? ? ? ? ? ? ? ?break; ? ? ? ?} ? ?}while(choice != 0); ? ?return 0; }

先不對(duì)4個(gè)用戶自定義函數(shù)進(jìn)行實(shí)現(xiàn),就用一個(gè)輸出語(yǔ)句來(lái)代替吧!

/*新建鏈表*/ struct stud_node * Create_Stu_Doc() ? { ? ?printf("你好,該模塊完成新建鏈表的功能\n"); } struct stud_node * InsertDoc(struct stud_node * head, struct stud_node *stud) { ? ? printf("你好,該模塊完成在鏈表中插入一個(gè)節(jié)點(diǎn)的功能\n"); ? ?/* ?*/ ? ? } struct stud_node * updateDoc(struct stud_node * head, int num) { ? ? printf("你好,該模塊完成修改功能\n"); ? ?/* 參數(shù)1:給我一個(gè)鏈表的頭指針,參數(shù)2:給我一個(gè)學(xué)號(hào),當(dāng)然是由其他函數(shù)傳入給我 */ ? ? } struct stud_node * DeleteDoc(struct stud_node * head, int num) { ? ? printf("你好,該模塊完成刪除鏈表的一個(gè)節(jié)點(diǎn)的功能\n"); ? ?/* 參數(shù)1:給我一個(gè)鏈表的頭指針,參數(shù)2:給我一個(gè)要?jiǎng)h除學(xué)生的學(xué)號(hào),當(dāng)然是由其他函數(shù)傳入給我 */ ? ? } void Print_Stu_Doc(struct stud_node * head) { ? ?printf("你好,該模塊完成瀏覽即遍歷整個(gè)鏈表中所有數(shù)據(jù)的功能\n"); ? ?/* 參數(shù)1:給我一個(gè)鏈表的頭指針即可*/ }

那將上述兩部分代碼放在一個(gè)文件中,那豈不是可以運(yùn)行了呢?來(lái)試試吧!


問(wèn):有同學(xué)問(wèn),這樣的菜單也不好看呀,能不能變個(gè)樣子呀!當(dāng)然可以了

嘗試寫一個(gè)menu函數(shù),就單干輸出菜單行不行?讓主函數(shù)開(kāi)始調(diào)用它,看看行不行唄!

void menu() { ? ?printf("\n\n***************************\n"); ? ? ? ?printf("\t1:新建鏈表\n\n\t2:插入一個(gè)節(jié)點(diǎn)\n\n\t3:修改一個(gè)結(jié)點(diǎn)\n\n\t4:刪除一個(gè)結(jié)點(diǎn)\n\n\t5:瀏覽所有信息\n\n\t0:退出系統(tǒng)\n"); ? ? ? ?printf("***************************\n"); }

那就修改一下主函數(shù)吧!如下:

#include<stdio.h> #include<stdlib.h> #include<string.h> struct stud_node{ ? ?int num; ? ?char name[20]; ? ?int score; ? ?struct stud_node *next; }; void menu();/* 顯示菜單 ? 可別忘記這里對(duì)菜單函數(shù)進(jìn)行聲明呀,具體menu函數(shù)實(shí)現(xiàn),放到最后一個(gè)函數(shù)后面*/ struct stud_node * Create_Stu_Doc(); ?/* 新建鏈表 */ struct stud_node * InsertDoc(struct stud_node * head, struct stud_node *stud); /* 插入 */ struct stud_node * updateDoc(struct stud_node * head, int num); /* 修改 */ struct stud_node * DeleteDoc(struct stud_node * head, int num); ?/* 刪除 */ void Print_Stu_Doc(struct stud_node * head); ?/* 遍歷 */ int main(void) { ? ?struct stud_node *head, *p; ? ?int choice, num, score; ? ?char name[20]; ? ?int size = sizeof(struct stud_node); ? ?do{ ? ? ? ? menu();/* 這個(gè)地方就是調(diào)用菜單menu函數(shù)!*/ ? ? ? ?scanf("%d", &choice); ? ? ? ?switch(choice){ ? ? ? ? ? ?case 1: ? ? ? ? ? ? ? ?head = Create_Stu_Doc(); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 2: ? ? ? ? ? ? ? ?/* ? ? ? ? ? ? ? ?printf("Input num,name and score:\n"); ? ? ? ? ? ? ? ?scanf("%d%s%d", &num,name, &score); ? ? ? ? ? ? ? ?p = (struct stud_node *) malloc(size); ? ? ? ? ? ? ? ?p->num = num; ? ? ? ? ? ? ? ?strcpy(p->name, name); ? ? ? ? ? ? ? ?p->score = score; ? ? ? ? ? ? ? ?*/ ? ? ? ? ? ? ? ?head = InsertDoc(head, p); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 3: ? ? ? ? ? ? ? ?scanf("%d", &num); ? ? ? ? ? ? ? ?head = updateDoc(head, num); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 4: ? ? ? ? ? ? ? ?printf("Input num:\n"); ? ? ? ? ? ? ? ?scanf("%d", &num); ? ? ? ? ? ? ? ?head = DeleteDoc(head, num); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 5: ? ? ? ? ? ? ? ?Print_Stu_Doc(head); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 0: ? ? ? ? ? ? ? ?break; ? ? ? ?} ? ?}while(choice != 0); ? ?return 0; }

問(wèn):有同學(xué)說(shuō),還不夠好看呀,不能顯示跟系統(tǒng)有關(guān)的內(nèi)容呀?

答:那就直接修改menu函數(shù)即可,其他的不用動(dòng)即可!

繼續(xù)修改menu函數(shù)

void menu() { ? ?printf("\n\n********青果學(xué)生信息管理系統(tǒng)*************\n\n"); ? ? ? ?printf("\t1:新建一個(gè)學(xué)生信息鏈表\n\n\t2:插入一個(gè)學(xué)生信息\n\n\t3:修改一個(gè)學(xué)生信息\n\n\t4:刪除一個(gè)學(xué)生信息\n\n\t5:瀏覽所有學(xué)生信息\n\n\t0:退出學(xué)生信息系統(tǒng)\n"); ? ? ? ?printf("**************************************\n"); }

是不是感覺(jué)好多了?嗯!

問(wèn):那功能沒(méi)有實(shí)現(xiàn)呀?

答:不要急,接下來(lái)就開(kāi)始啦!將每一個(gè)函數(shù)的實(shí)現(xiàn)過(guò)程替換掉對(duì)應(yīng)函數(shù)肚子的那個(gè)輸出語(yǔ)句!

第一:以新建鏈表的函數(shù)為例Create_Stu_Doc,其內(nèi)部實(shí)現(xiàn),是需要調(diào)用節(jié)點(diǎn)插入InsertDoc函數(shù),那這兩個(gè)函數(shù)要一起實(shí)現(xiàn),要不然,光一個(gè)Create_Stu_Doc可不夠呀!

第二,那寫的對(duì)不對(duì)也需要測(cè)試,比如說(shuō):你創(chuàng)建成功了一個(gè)學(xué)生信息單鏈表,那到底創(chuàng)建成功沒(méi)有?,那就趕緊把遍歷即瀏覽函數(shù)Print_Stu_Doc寫一下,這樣,調(diào)用輸出一下,不就可以更好地看一下是否創(chuàng)建成功了沒(méi)有?

第三:當(dāng)你寫好了修改函數(shù),和刪除函數(shù),是不是也需要測(cè)試一下,也離不開(kāi)瀏覽函數(shù)Print_Stu_Doc,所以,Print_Stu_Doc必須是正確無(wú)誤的呀!

來(lái),一步一步啦,不要急

先寫Create_Stu_Doc函數(shù),來(lái)吧

注意,我們講課時(shí),都希望你創(chuàng)建的是帶頭節(jié)點(diǎn)的單鏈表,那下面的代碼是創(chuàng)建的是啥鏈表呢??

你看,它調(diào)用的是一個(gè)InsertDoc(head, p)函數(shù),那我們看看

/*新建鏈表*/ struct stud_node * Create_Stu_Doc() ? { ? ?struct stud_node * head,*p; ? ?int num,score; ? ?char ?name[20]; ? ?int size = sizeof(struct stud_node); ? ?head = NULL; ? ?printf("Input num,name and score:\n"); ? ?scanf("%d%s%d", &num,name, &score); ? ?while(num != 0){ ? ? ? p = (struct stud_node *) malloc(size); ? ? ? p->num = num; ? ? ? strcpy(p->name, name); ? ? ? p->score = score; ? ? ? head = InsertDoc(head, p); ? ?/* 調(diào)用插入函數(shù) */ ? ? ? scanf("%d%s%d", &num, name, &score); ? } ? return head; }

一起讀一下下面的insertDoc函數(shù)吧,區(qū)別于我們講過(guò)的,你看一下,

該函數(shù)兩個(gè)參數(shù),一個(gè)是給我一個(gè)鏈表,第二個(gè)參數(shù),就是傳給我的一個(gè)學(xué)生結(jié)構(gòu)體變量的指針

然后呢?這個(gè)學(xué)生要插入到什么位置呢?下面的代碼仔細(xì)看呀!

情況1:若給我傳過(guò)來(lái)的head為NULL,即是空鏈表,新來(lái)的這個(gè)就是第一個(gè)結(jié)點(diǎn)(這說(shuō)明這個(gè)算法是否考慮頭結(jié)點(diǎn))

情況2: if(ptr->num <= ptr2->num) ?就是判斷一下傳入的這個(gè)學(xué)生的學(xué)號(hào),如果是處于兩個(gè)學(xué)生節(jié)點(diǎn)的學(xué)號(hào)之間,那就插入到這兩個(gè)學(xué)生節(jié)點(diǎn)之間; ? 這點(diǎn)區(qū)別于我們之前講過(guò)的頭插,尾插,而是按照學(xué)號(hào)的順序插入呀,這就是靈活變化呀,根據(jù)題目的要求來(lái)變化呀! ? ? ?

情況3:就是else的后面的,不是第一個(gè),也不是中間的,那就放到單鏈表的最后,作為尾節(jié)點(diǎn)!

/* 插入操作 */ struct stud_node * InsertDoc(struct stud_node * head, struct stud_node *stud) ? { ? ? struct stud_node *ptr ,*ptr1, *ptr2; ? ?ptr2 = head; ? ?ptr = stud; /* ptr指向待插入的新的學(xué)生記錄結(jié)點(diǎn) */ ? ?/* 原鏈表為空時(shí)的插入 */ ? ?if(head == NULL){ ? ? ? ?head = ptr; /* 新插入結(jié)點(diǎn)成為頭結(jié)點(diǎn) */ ? ? ? ?head->next = NULL; ? ?} ? ?else{ ? ?/* 原鏈表不為空時(shí)的插入 */ ? ? ? ? while((ptr->num > ptr2->num) && (ptr2->next != NULL)){ ? ? ? ? ? ?ptr1 = ptr2; /* ptr1, ptr2各后移一個(gè)結(jié)點(diǎn) */ ? ? ? ? ? ?ptr2 = ptr2->next; ? ? ? ? } ? ? ? ? if(ptr->num <= ptr2->num){ /* 在ptr1與ptr2之間插入新結(jié)點(diǎn) */ ? ? ? ? ? ?if(head == ptr2){ head = ptr; ? ? ? ? ? ?}else{ ptr1->next = ptr; } ? ? ? ? ? ?ptr->next = ptr2; ? ? ? ?}else{ ? ?/* 新插入結(jié)點(diǎn)成為尾結(jié)點(diǎn) */ ? ? ? ? ? ?ptr2->next = ptr; ? ? ? ? ? ?ptr->next = NULL; ? ? ? ?} ? ?} ? ? ? ?return head; }

不管如何,那為了驗(yàn)證新建鏈表函數(shù)和插入節(jié)點(diǎn)函數(shù)是否成功,還需要寫一下瀏覽函數(shù),這個(gè)函數(shù)實(shí)現(xiàn)很簡(jiǎn)單,就是給我一個(gè)單鏈表的頭指針,我來(lái)“順藤摸瓜”輸出每個(gè)學(xué)生節(jié)點(diǎn)的內(nèi)容!

/*遍歷操作*/ void Print_Stu_Doc(struct stud_node * head) { ? struct stud_node * ptr; ? ?if(head == NULL){ ? ? ? ?printf("\n對(duì)不起,該學(xué)生鏈表中沒(méi)有數(shù)據(jù)\n"); ? ? ? ?return; ? ?} ? ?printf("\nThe Students' Records Are: \n"); ? ?printf("Num\t Name\t Score\n"); ? ?for(ptr = head; ptr != NULL; ptr = ptr->next){ ? ? ? printf("%d\t%s\t%d \n", ptr->num, ptr->name, ptr->score); ? ?} }

那這樣吧,我們就把主函數(shù)也弄過(guò)來(lái),把調(diào)用Create_Stu_Doc、InsertDoc、 Print_Stu_Doc三個(gè)函數(shù)的對(duì)應(yīng)的注釋去掉吧

這里我給一個(gè)相對(duì)完整的代碼吧!

#include<stdio.h> #include<stdlib.h> #include<string.h> struct stud_node{ ? ?int num; ? ?char name[20]; ? ?int score; ? ?struct stud_node *next; }; void menu();/* 顯示菜單*/ struct stud_node * Create_Stu_Doc(); ?/* 新建鏈表 */ struct stud_node * InsertDoc(struct stud_node * head, struct stud_node *stud); /* 插入 */ struct stud_node * updateDoc(struct stud_node * head, int num); /* 修改 */ struct stud_node * DeleteDoc(struct stud_node * head, int num); ?/* 刪除 */ void Print_Stu_Doc(struct stud_node * head); ?/* 遍歷 */ int main(void) { ? ?struct stud_node *head, *p; ? ?int choice, num, score; ? ?char name[20]; ? ?int size = sizeof(struct stud_node); ? ?do{ ? ? ? ? menu(); ? ? ? ?scanf("%d", &choice); ? ? ? ?switch(choice){ ? ? ? ? ? ?case 1: ? ? ? ? ? ? ? ?head = Create_Stu_Doc(); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 2: ? ? ? ? ? ? ? ?printf("Input num,name and score:\n"); ? ? ? ? ? ? ? ?scanf("%d%s%d", &num,name, &score); ? ? ? ? ? ? ? ?p = (struct stud_node *) malloc(size); ? ? ? ? ? ? ? ?p->num = num; ? ? ? ? ? ? ? ?strcpy(p->name, name); ? ? ? ? ? ? ? ?p->score = score; ? ? ? ? ? ? ? ?head = InsertDoc(head, p); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 3: ? ? ? ? ? ? ? ?scanf("%d", &num); ? ? ? ? ? ? ? ?head = updateDoc(head, num); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 4: ? ? ? ? ? ? ? ?printf("Input num:\n"); ? ? ? ? ? ? ? ?scanf("%d", &num); ? ? ? ? ? ? ? ?head = DeleteDoc(head, num); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 5: ? ? ? ? ? ? ? ?Print_Stu_Doc(head); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case 0: ? ? ? ? ? ? ? ?break; ? ? ? ?} ? ?}while(choice != 0); ? ?return 0; } /*新建鏈表*/ struct stud_node * Create_Stu_Doc() { ? ?struct stud_node * head,*p; ? ?int num,score; ? ?char ?name[20]; ? ?int size = sizeof(struct stud_node); ? ?head = NULL; ? ?printf("Input num,name and score:\n"); ? ?scanf("%d%s%d", &num,name, &score); ? ?while(num != 0){ ? ? ? p = (struct stud_node *) malloc(size); ? ? ? p->num = num; ? ? ? strcpy(p->name, name); ? ? ? p->score = score; ? ? ? head = InsertDoc(head, p); ? ?/* 調(diào)用插入函數(shù) */ ? ? ? scanf("%d%s%d", &num, name, &score); ? } return head; } /* 插入操作 */ struct stud_node * InsertDoc(struct stud_node * head, struct stud_node *stud) { ? struct stud_node *ptr ,*ptr1, *ptr2; ? ?ptr2 = head; ? ?ptr = stud; /* ptr指向待插入的新的學(xué)生記錄結(jié)點(diǎn) */ ? ?/* 原鏈表為空時(shí)的插入 */ ? ?if(head == NULL){ ? ? ? ?head = ptr; /* 新插入結(jié)點(diǎn)成為頭結(jié)點(diǎn) */ ? ? ? ?head->next = NULL; ? ?} ? ?else{ ? ?/* 原鏈表不為空時(shí)的插入 */ ? ? ? ? while((ptr->num > ptr2->num) && (ptr2->next != NULL)){ ? ? ? ? ? ?ptr1 = ptr2; /* ptr1, ptr2各后移一個(gè)結(jié)點(diǎn) */ ? ? ? ? ? ?ptr2 = ptr2->next; ? ? ? ? } ? ? ? ? if(ptr->num <= ptr2->num){ /* 在ptr1與ptr2之間插入新結(jié)點(diǎn) */ ? ? ? ? ? ?if(head == ptr2){ head = ptr; ? ? ? ? ? ?}else{ ptr1->next = ptr; } ? ? ? ? ? ?ptr->next = ptr2; ? ? ? ?}else{ ? ?/* 新插入結(jié)點(diǎn)成為尾結(jié)點(diǎn) */ ? ? ? ? ? ?ptr2->next = ptr; ? ? ? ? ? ?ptr->next = NULL; ? ? ? ?} ? ?} ? ?return head; } struct stud_node * updateDoc(struct stud_node * head, int num) { ? ? printf("你好,該模塊完成修改功能\n"); ? ?/* 參數(shù)1:給我一個(gè)鏈表的頭指針,參數(shù)2:給我一個(gè)學(xué)號(hào),當(dāng)然是由其他函數(shù)傳入給我 */ } struct stud_node * DeleteDoc(struct stud_node * head, int num) { ? ? printf("你好,該模塊完成刪除鏈表的一個(gè)節(jié)點(diǎn)的功能\n"); ? ?/* 參數(shù)1:給我一個(gè)鏈表的頭指針,參數(shù)2:給我一個(gè)要?jiǎng)h除學(xué)生的學(xué)號(hào),當(dāng)然是由其他函數(shù)傳入給我 */ } /*遍歷操作*/ void Print_Stu_Doc(struct stud_node * head) { struct stud_node * ptr; ? ?if(head == NULL){ ? ? ? ?printf("\nNo Records\n"); ? ? ? ?return; ? ?} ? ?printf("\nThe Students' Records Are: \n"); ? ?printf("Num\t Name\t Score\n"); ? ?for(ptr = head; ptr != NULL; ptr = ptr->next){ ? ? ? printf("%d\t%s\t%d \n", ptr->num, ptr->name, ptr->score); ? ?} } void menu() { ? ?printf("\n\n********青果學(xué)生信息管理系統(tǒng)*************\n\n"); ? ? ? ?printf("\t1:新建一個(gè)學(xué)生信息鏈表\n\n\t2:插入一個(gè)學(xué)生信息\n\n\t3:修改一個(gè)學(xué)生信息\n\n\t4:刪除一個(gè)學(xué)生信息\n\n\t5:瀏覽所有學(xué)生信息\n\n\t0:退出學(xué)生信息系統(tǒng)\n"); ? ? ? ?printf("**************************************\n"); }

此處,也是一個(gè)可以改進(jìn)的地方呀,難道必須每次都得輸入0以后,還得輸入一個(gè)姓名和分?jǐn)?shù)才行嗎?

如何改進(jìn)呢?你答辯的時(shí)候,是不是可以給我炫耀一下,你是如何改進(jìn) 的呢?也是頭腦風(fēng)暴之一呀!

這里,三個(gè)函數(shù)都通過(guò)測(cè)試,那至于刪除函數(shù)和修改函數(shù),你自行補(bǔ)充進(jìn)去,是不是就可以了呢?

你來(lái)做吧!

這里我假定你已經(jīng)補(bǔ)充進(jìn)去了!

至此,你是不是已經(jīng)對(duì)一個(gè)簡(jiǎn)單的學(xué)生信息管理系統(tǒng)有了了解呢!

那如何加上“文件”功能?不能每一次運(yùn)行,都讓我輸入大量的數(shù)據(jù)呀!

2.2 在上述“學(xué)生信息管理系統(tǒng)”框架基礎(chǔ)上加上“文件“的功能(未寫完)

思考一下:

文件的作用是什么?在什么時(shí)候使用?

答:

場(chǎng)景1:最簡(jiǎn)單的場(chǎng)景,就是事先已經(jīng)有一個(gè)文件,里面按照格式已經(jīng)錄入了若干條學(xué)生的信息數(shù)據(jù);在程序運(yùn)行的時(shí)候,先用一個(gè)load函數(shù),就是讀入該文件,將該文件讀入到單鏈表中或者結(jié)構(gòu)體數(shù)組中,那后面的至于插入操作、增加操作、刪除操作,修改操作、查詢操作等,都在單鏈表或者結(jié)構(gòu)體數(shù)組上完成,等最后退出整個(gè)系統(tǒng)的時(shí)候,調(diào)用一個(gè)save函數(shù),即再把單鏈表或者結(jié)構(gòu)體數(shù)組中的數(shù)據(jù)寫回到文件中,就可以了!

場(chǎng)景2:假如是第一次使用該系統(tǒng),那必然沒(méi)有該數(shù)據(jù)文件啦,那程序應(yīng)該可以提醒創(chuàng)建一個(gè)文件,然后,你錄入的數(shù)據(jù),就可以存入到該文件中

那我們回來(lái)看一下我們已經(jīng)寫好的代碼里,是如何創(chuàng)建起來(lái)鏈表的呢?

現(xiàn)有的代碼的流程是:選擇1,調(diào)用 head = Create_Stu_Doc();這個(gè)函數(shù),

Create_Stu_Doc()函數(shù)的具體實(shí)現(xiàn)為:

struct stud_node * Create_Stu_Doc() { ? ?struct stud_node * head,*p; ? ?int num,score; ? ?char ?name[20]; ? ?int size = sizeof(struct stud_node); ? ?head = NULL; ? ?printf("Input num,name and score:\n"); ? ?scanf("%d%s%d", &num,name, &score); ? ?while(num != 0){ ? ? ? p = (struct stud_node *) malloc(size); ? ? ? p->num = num; ? ? ? strcpy(p->name, name); ? ? ? p->score = score; ? ? ? head = InsertDoc(head, p); ? ?/* 調(diào)用插入函數(shù) */ ? ? ? scanf("%d%s%d", &num, name, &score); ? } return head; }

觀察一下,循環(huán)地 scanf("%d%s%d", &num,name, &score); ?就是循環(huán)地讀取數(shù)據(jù),那我們能否將這里的數(shù)據(jù)的讀入,改為從文件讀入呢?即,讀一行數(shù)據(jù),創(chuàng)建一個(gè)節(jié)點(diǎn),鏈接進(jìn)鏈表,那讀取到最后,不就是創(chuàng)建完成了?





擴(kuò)展功能的頭腦風(fēng)暴(未寫完)

你自己實(shí)現(xiàn)的任何你自己覺(jué)得是頭腦風(fēng)暴中的功能,都可以在答辯的時(shí)候給我闡述出來(lái),不要怕小,其實(shí)小功能也能體現(xiàn)出不少的細(xì)節(jié)!

程序整體以及功能方面:

(1)就各個(gè)系統(tǒng)而言,例:若只完成圖書(shū)管理的圖書(shū)管理系統(tǒng),也確實(shí)能夠滿足基本要求,若能夠進(jìn)一步完成圖書(shū)借閱功能,那將是一個(gè)不錯(cuò)的功能擴(kuò)展,比如學(xué)生成績(jī)管理系統(tǒng),加上課程的管理,以及對(duì)應(yīng)成績(jī)的管理,也是功能的擴(kuò)展。

(2)多文件包含:將寫好的一個(gè)很大很長(zhǎng)的程序,進(jìn)行拆解,寫成多文件包含的形式!雖然是在設(shè)計(jì)之初就應(yīng)該將這些搞定,很多同學(xué)都是寫好程序之后,才想著拆分,其實(shí)也是一個(gè)好主意!也避免拆壞了!

(3)具體功能實(shí)現(xiàn),能否利用一些非課堂中學(xué)習(xí)的算法來(lái)實(shí)現(xiàn);(比如排序,除了學(xué)習(xí)過(guò)的冒泡和選擇排序外,自己能夠自學(xué)數(shù)據(jù)結(jié)構(gòu)課程中的其他排序算法,并實(shí)現(xiàn),那也就鍛煉了自學(xué)能力)

細(xì)節(jié):

(1)錄入數(shù)據(jù)的時(shí)候,學(xué)號(hào)是否重復(fù)呢?如何處理呢?

(2)錄入數(shù)據(jù)的時(shí)候,學(xué)號(hào)、身份證號(hào)等類似的信息,通常有固定的長(zhǎng)度,若用戶輸入錯(cuò)誤了,程序應(yīng)該有類似于校驗(yàn)并提示的功能;

(3)身份證號(hào)與出生日期是否一致?這其實(shí)也是一個(gè)校驗(yàn)的功能;要想實(shí)現(xiàn),當(dāng)然也需要寫一個(gè)小的函數(shù)呀!

(4)刪除數(shù)據(jù)的時(shí)候的提示信息“確定要?jiǎng)h除”等人性化的處理細(xì)節(jié);

(5)查詢功能的處理,可以嘗試實(shí)現(xiàn)比如模糊查詢,組合查詢等功能,比如查詢一下圖書(shū)名稱含有為“程序設(shè)計(jì)”字樣的圖書(shū)、組合查詢:比如查詢一下“清華大學(xué)出版社”出版的含有“程序設(shè)計(jì)”字樣的圖書(shū)等等

(6)各類報(bào)表的輸出,自己想一些功能,比如導(dǎo)出**個(gè)學(xué)院的借閱圖書(shū)前十名的學(xué)生,導(dǎo)出到某一個(gè)文檔中,其實(shí)就是一個(gè)寫入數(shù)據(jù)到另一個(gè)文件的過(guò)程;

(7)數(shù)據(jù)導(dǎo)入功能的設(shè)計(jì),其實(shí)就是從一個(gè)文件中讀出,寫入到另外一個(gè)文件中。

所以,你會(huì)發(fā)現(xiàn),所謂的細(xì)節(jié),實(shí)現(xiàn)起來(lái)呢,并不是很難,就是要去想,要站到用戶的角度去想,哪些功能和細(xì)節(jié)是容易忽略的,然后,你將它設(shè)計(jì)出來(lái)。


《學(xué)生信息管理系統(tǒng)》案例設(shè)計(jì)過(guò)程的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
邵东县| 涞源县| 绥芬河市| 东乌珠穆沁旗| 西峡县| 瑞安市| 新疆| 西昌市| 瑞安市| 上思县| 德格县| 库伦旗| 长治市| 定兴县| 蒲江县| 洪江市| 抚顺市| 资源县| 乌拉特后旗| 龙泉市| 崇仁县| 日土县| 金乡县| 多伦县| 湛江市| 新竹县| 玉树县| 桓台县| 增城市| 衡阳县| 铜川市| 崇左市| 保定市| 溆浦县| 灯塔市| 望奎县| 吉木乃县| 和田市| 鹤峰县| 百色市| 珲春市|