整體練習(xí)-學(xué)生管理系統(tǒng)
在學(xué)習(xí)的最后,我們?yōu)榇蠹覝?zhǔn)備了一個(gè)比較綜合的練習(xí),這里會(huì)用到很多我們前面所學(xué)習(xí)到的知識(shí)。
1. 系統(tǒng)介紹
在這里,我們首先采用了數(shù)組的方式來存儲(chǔ)我們輸入的內(nèi)容。同時(shí),我們這里利用里前面學(xué)習(xí)到的 struct
來結(jié)構(gòu)化存儲(chǔ)我們的學(xué)生信息。
我們實(shí)現(xiàn)了基本的對(duì)于數(shù)據(jù)操作的幾項(xiàng)功能:增、刪、改、查。
也就是我們可以向這個(gè)系統(tǒng)中添加數(shù)據(jù),刪除數(shù)據(jù),修改數(shù)據(jù),還有就是查詢數(shù)據(jù)。這里的查詢數(shù)據(jù),我們又分為了全部無條件的查詢,和按照姓名條件的查詢。
2. 功能
系統(tǒng)的功能里面我們?cè)O(shè)計(jì)了添加、刪除、修改、列表顯示和查詢等 5 個(gè)功能。
添加:添加就是將數(shù)據(jù)添加到存儲(chǔ)數(shù)據(jù)的數(shù)組中;
刪除:刪除就是根據(jù)指定的序列號(hào)刪除特定的一條數(shù)據(jù);
修改:修改就是根據(jù)指定的序列號(hào)來修改學(xué)生的成績(jī);
列表顯示:列表的顯示,其實(shí)就是無條件的查詢,也就是在沒有特點(diǎn)查詢條件的情況下,將存儲(chǔ)的數(shù)據(jù)全部顯示出來;
查詢:這里的查詢,就是按照姓名這個(gè)特性的條件。把符合這個(gè)條件的數(shù)據(jù)篩選出來,并顯示出來。
3. 示例程序
#include <stdio.h>
#include <string.h>
#define StudentNumbers 50
#define NameLength 50
typedef struct
{
int id;
char name[NameLength];
int age;
int score;
int flag;
} Student;
int add(Student student, Student Students[]);
int del(int id, Student students[]);
int display(Student students[]);
int update(int id, Student students[]);
int search(char name[], Student students[]);
int main()
{
int id = -1;
char name[NameLength];
int choice = 0;
int stop = 0;
Student students[StudentNumbers];
Student student;
for (int i = 0; i < StudentNumbers; i++)
{
students[i].id = i;
students[i].flag = 0;
}
while (stop == 0)
{
printf("-------------------------\n");
printf("* 學(xué)生管理系統(tǒng) *\n");
printf("-------------------------\n");
printf("1 添加\n");
printf("2 修改成績(jī)\n");
printf("3 查詢\n");
printf("4 刪除\n");
printf("5 顯示學(xué)生列表\n");
printf("0 退出程序\n");
printf("請(qǐng)直接輸入數(shù)字選項(xiàng):");
scanf("%d", &choice);
switch (choice)
{
case 1:
printf("請(qǐng)輸入學(xué)生姓名:");
scanf("%s", student.name);
printf("請(qǐng)輸入學(xué)生的年齡:");
scanf("%d", &student.age);
printf("請(qǐng)輸入學(xué)生成績(jī):");
scanf("%d", &student.score);
add(student, students);
break;
case 2:
printf("請(qǐng)輸入要修改成績(jī)的學(xué)生編號(hào):");
scanf("%d", &id);
update(id, students);
break;
case 3:
printf("請(qǐng)輸入要查找的學(xué)生姓名:");
scanf("%s", name);
search(name, students);
break;
case 4:
printf("請(qǐng)輸入要?jiǎng)h除的學(xué)生編號(hào):");
scanf("%d", &id);
del(id, students);
break;
case 5:
display(students);
break;
case 0:
stop = 1;
break;
default:
printf("輸入選項(xiàng)有誤\n");
break;
}
}
return 0;
}
int add(Student student, Student students[])
{
for (int i = 0; i < StudentNumbers; i++)
{
if (students[i].flag == 0)
{
strcpy(students[i].name, student.name);
students[i].age = student.age;
students[i].score = student.score;
students[i].flag = 1;
return 0;
}
}
return 1;
}
int del(int id, Student students[])
{
for (int i = 0; i < StudentNumbers; i++)
{
if (students[i].id == id)
{
students[i].flag = 0;
return 0;
}
}
return 1;
}
int display(Student students[])
{
printf("******************\n");
printf("學(xué)生列表\n");
printf("******************\n");
for (int i = 0; i < StudentNumbers; i++)
{
if (students[i].flag == 1)
{
printf("學(xué)生編號(hào):%d,學(xué)生姓名:%s,年齡:%d,成績(jī):%d\n", students[i].id, students[i].name, students[i].age, students[i].score);
}
}
printf("******************\n");
return 0;
}
int update(int id, Student students[])
{
int score = -1;
printf("請(qǐng)輸入新的成績(jī):");
scanf("%d", &score);
for (int i = 0; i < StudentNumbers; i++)
{
if (students[i].id == id)
{
students[i].score = score;
return 0;
}
}
return 1;
}
int search(char name[], Student students[])
{
for (int i = 0; i < StudentNumbers; i++)
{
if (strcmp(name, students[i].name) == 0)
{
printf("學(xué)生編號(hào): %d,學(xué)生姓名: %s,年齡: %d,成績(jī): %d\n", students[i].id, students[i].name, students[i].age, students[i].score);
return 0;
}
}
printf("沒有查找到相關(guān)學(xué)生信息。\n");
return 1;
}
很多人可能會(huì)第一次接觸這么長(zhǎng)的程序,會(huì)產(chǎn)生畏懼的心理。其實(shí)不用擔(dān)心。要相信自己可以看懂的。
我們分開來講解一下。
在程序的最開始我們需要引入程序中可能需要使用的函數(shù)的頭文件。這里我們因?yàn)橐褂?printf
、 scanf
等,所以需要 stdio
函數(shù)庫。因?yàn)橐褂?strcpy
、 strcmp
函數(shù),所以需要 string
函數(shù)庫。
#include <stdio.h>
#include <string.h>
為了便于程序中的維護(hù),不用在很多出修改共用的數(shù)值。所以這里定義了一個(gè)常量
#define StudentNumbers 50
#define NameLength 50
為了存儲(chǔ)學(xué)生的信息。我們用了 struct
來定義學(xué)生的信息。里面包含學(xué)生的編號(hào) id
,姓名 name
這是一個(gè)字符串,年齡 age
,成績(jī) score
,標(biāo)志位 flag
這個(gè)變量是用來表示是否有學(xué)生信息存儲(chǔ)在該位置的。不過這里我們使用了之前沒有介紹的一個(gè) typedef
。這個(gè)關(guān)鍵字使用的好處是使得后面使用這個(gè) struct
的時(shí)候不用每次都用關(guān)鍵字 struct
來定義,只要用這個(gè)結(jié)構(gòu)的名稱直接定義就可以了,如同我們定義整數(shù)等內(nèi)置類型一樣方便。
typedef struct
{
int id;
char name[NameLength];
int age;
int score;
int flag;
} Student;
為了便于維護(hù),我們沒有按照函數(shù)出現(xiàn)的順序來寫。不過 C 語言一直秉承著先定義再使用的原則。所以。如果你使用的函數(shù)沒有在使用前出現(xiàn),而是在后面的話,那么你就需要先讓編譯器知道這個(gè)函數(shù)的基本情況。這個(gè)時(shí)候我們會(huì)先把函數(shù)的定義寫在前面。
我們可以看到下面我們定義了這個(gè)系統(tǒng)的功能。每個(gè)功能我們都會(huì)寫一個(gè)函數(shù)。其實(shí)不寫這些函數(shù),把所有的功能寫在 main
函數(shù)內(nèi)部也是可以的。但是這樣會(huì)在維護(hù)上存在問題。進(jìn)行測(cè)試也會(huì)變得困難。
int add(Student student, Student Students[]);
int del(int id, Student students[]);
int display(Student students[]);
int update(int id, Student students[]);
int search(char name[], Student students[]);
這里定義了一些需要使用的變量。stop
變量是用來控制程序循環(huán)的,也就是控制程序在什么時(shí)候可以結(jié)束循環(huán)的。我們定義了一個(gè) Student
的數(shù)組,用來存儲(chǔ)學(xué)生的信息。用一個(gè)單獨(dú)的變量來存儲(chǔ)單條的學(xué)生信息。
int id = -1;
char name[NameLength];
int choice = 0;
int stop = 0;
Student students[StudentNumbers];
Student student;
這里我們通過循環(huán)來初始化我們的數(shù)組。
for (int i = 0; i < StudentNumbers; i++)
{
students[i].id = i;
students[i].flag = 0;
}
循環(huán)語句如果在不改變條件的情況下會(huì)一直循環(huán)。確保我們的系統(tǒng)可以一直運(yùn)行。
while (stop == 0)
在接收到輸入后。我們就會(huì)通過 switch
來進(jìn)行相應(yīng)的匹配。完成對(duì)應(yīng)的操作。這比使用大量的 if
語句簡(jiǎn)約了很多。
switch (choice)
在子程序中,也就是實(shí)現(xiàn)增、刪、改、查這些功能程序中。我們用了循環(huán)語句來訪問數(shù)組中的元素。同時(shí),利用了判斷語句與特定的變量,來判斷該位置是否存有學(xué)生信息。
運(yùn)行結(jié)果:
utopia@DESKTOP:~$ ./test
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):1
請(qǐng)輸入學(xué)生姓名:張三
請(qǐng)輸入學(xué)生的年齡:22
請(qǐng)輸入學(xué)生成績(jī):100
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):1
請(qǐng)輸入學(xué)生姓名:李四
請(qǐng)輸入學(xué)生的年齡:21
請(qǐng)輸入學(xué)生成績(jī):90
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):1
請(qǐng)輸入學(xué)生姓名:王二
請(qǐng)輸入學(xué)生的年齡:23
請(qǐng)輸入學(xué)生成績(jī):99
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):5
******************
學(xué)生列表
******************
學(xué)生編號(hào):0,學(xué)生姓名:張三,年齡:22,成績(jī):100
學(xué)生編號(hào):1,學(xué)生姓名:李四,年齡:21,成績(jī):90
學(xué)生編號(hào):2,學(xué)生姓名:王二,年齡:23,成績(jī):99
******************
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):2
請(qǐng)輸入要修改成績(jī)的學(xué)生編號(hào):1
請(qǐng)輸入新的成績(jī):80
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):5
******************
學(xué)生列表
******************
學(xué)生編號(hào):0,學(xué)生姓名:張三,年齡:22,成績(jī):100
學(xué)生編號(hào):1,學(xué)生姓名:李四,年齡:21,成績(jī):80
學(xué)生編號(hào):2,學(xué)生姓名:王二,年齡:23,成績(jī):99
******************
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):4
請(qǐng)輸入要?jiǎng)h除的學(xué)生編號(hào):1
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):5
******************
學(xué)生列表
******************
學(xué)生編號(hào):0,學(xué)生姓名:張三,年齡:22,成績(jī):100
學(xué)生編號(hào):2,學(xué)生姓名:王二,年齡:23,成績(jī):99
******************
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):1
請(qǐng)輸入學(xué)生姓名:張五
請(qǐng)輸入學(xué)生的年齡:20
請(qǐng)輸入學(xué)生成績(jī):70
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):5
******************
學(xué)生列表
******************
學(xué)生編號(hào):0,學(xué)生姓名:張三,年齡:22,成績(jī):100
學(xué)生編號(hào):1,學(xué)生姓名:張五,年齡:20,成績(jī):70
學(xué)生編號(hào):2,學(xué)生姓名:王二,年齡:23,成績(jī):99
******************
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):3
請(qǐng)輸入要查找的學(xué)生姓名:張五
學(xué)生編號(hào): 1,學(xué)生姓名: 張五,年齡: 20,成績(jī): 70
-------------------------
* 學(xué)生管理系統(tǒng) *
-------------------------
1 添加
2 修改成績(jī)
3 查詢
4 刪除
5 顯示學(xué)生列表
0 退出程序
請(qǐng)直接輸入數(shù)字選項(xiàng):
在程序中,我們首先添加了 3 條學(xué)生的記錄。然后我們進(jìn)行了列表顯示。接著,我們嘗試修改了其中一個(gè)學(xué)生成績(jī),并再次查看列表,發(fā)現(xiàn)成績(jī)修改生效了。然后,我們刪除了一個(gè)學(xué)生,列表顯示結(jié)果其已經(jīng)被刪除了。然后我們又嘗試添加了一個(gè)學(xué)生。列表顯示結(jié)果添加成功。最后我們按照姓名查找了一個(gè)學(xué)生。
4. 小結(jié)
在這里,我們知識(shí)綜合利用了我們之前所學(xué)習(xí)的一部分知識(shí)來完成一個(gè)接近實(shí)際可用的系統(tǒng)。
當(dāng)然作為一個(gè)可以使用的系統(tǒng),我們還會(huì)設(shè)計(jì)到數(shù)據(jù)輸入時(shí)合法性的校驗(yàn),以及數(shù)據(jù)持久化的存儲(chǔ)等等一系列的問題需要考慮。
同時(shí)在一個(gè)系統(tǒng)規(guī)模變大以后,其存儲(chǔ)的結(jié)構(gòu)和方式會(huì)影響到數(shù)據(jù)的操作效率,最直觀的就是完成一次操作所需要的時(shí)間會(huì)發(fā)生較大甚至巨大的變化。這個(gè)時(shí)候,通過改善數(shù)據(jù)結(jié)構(gòu)與算法會(huì)起到非常重大的作用。但是切記實(shí)現(xiàn)功能在很多時(shí)候時(shí)一個(gè)系統(tǒng)的第一要?jiǎng)?wù),而優(yōu)化系統(tǒng)則是在你實(shí)現(xiàn)一個(gè)系統(tǒng)以后在做的事情。有本書中寫過,永遠(yuǎn)不要上來就設(shè)計(jì)一個(gè)龐大的系統(tǒng)。軟件的設(shè)計(jì)這個(gè)時(shí)候是另外一個(gè)重要的部分。我們這里既沒有考慮設(shè)計(jì),也沒有考慮算法與數(shù)據(jù)結(jié)構(gòu)。只是通過我們現(xiàn)有的知識(shí),來實(shí)現(xiàn)一個(gè)較為完整的功能。
學(xué)習(xí)沒有終點(diǎn),人生短暫而漫長(zhǎng)。需要你不斷的通過學(xué)習(xí)來找尋樂趣。不然這短暫的人生稍縱即逝,這漫長(zhǎng)的人生會(huì)讓你苦悶不堪。所以閑來沒事,用多種方式多學(xué)習(xí)一點(diǎn)。盡量找點(diǎn)可靠的信息來源看。謝謝大家!