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