在 C 語言教學與實戰中,「學生管理系統」是練習資料結構與模組化程式設計的經典案例。本文將帶你逐步探討四種不同的實現方式:一維陣列、二維陣列、指標、結構體,並附上完整原始碼與關鍵邏輯解析,幫助你理解資料封裝演進的脈絡。
最基礎的版本僅用一個 float a[N] 存放 5 位同學的單一科目成績。主選單提供「錄入、輸出、查詢、排序、退出」五大功能,密碼驗證採用三次機制。排序演算法使用選擇排序,由小到大輸出。
#include <stdio.h>
#include <string.h>
#define N 5
float a[N];
// 函數宣告...
void main() {
int x = mimayanzheng();
if (x == 1) {
caidan();
// 迴圈處理選單...
}
}
// 密碼驗證、選單顯示、錄入、輸出、查詢、排序函數實作...
優點:程式碼簡短,適合初學者理解陣列與函數模組化。
缺點:僅能處理單一科目,擴充性極差。
引入 float z[a][b](2 位學生 × 3 科),錄入與輸出皆採雙層迴圈。查詢與排序同樣在二維空間運作,排序針對每位學生的各科成績獨立進行。
#define a 2
#define b 3
float z[a][b];
void luru(float s[a][b]) {
for (int j = 0; j < a; j++)
for (int i = 0; i < b; i++)
scanf("%f", &s[j][i]);
}
// 其他函數同理調整為二維參數...
此版本展示如何用二維陣列模擬「學生×科目」的表格結構,但學生資訊(姓名、學號)仍缺失。
改用 double *a 指向陣列 double b[N],函數參數改為指標,透過 *(s+i) 存取元素。這不僅強化指標算術觀念,也為後續動態記憶體配置鋪路。
void luru(double *s, int n) {
for (int i = 0; i < n; i++) {
double k;
scanf("%lf", &k);
*(s + i) = k;
}
}
指標版本在邏輯上與一維陣列版同構,但語法更貼近底層記憶體操作。
定義 struct xitong 包含姓名、學號、三科成績。陣列 student[N] 成為學生記錄的集合,錄入時一次讀取所有欄位,輸出時格式化顯示。查詢可針對三科任一成績比對。
struct xitong {
char xingming[10];
int xuehao;
float yuwen, shuxue, yingyu;
};
void luru(struct xitong student[], int n) {
for (int i = 0; i < n; i++)
scanf("%s %d %f %f %f",
student[i].xingming, &student[i].xuehao,
&student[i].yuwen, &student[i].shuxue, &student[i].yingyu);
}
結構體版本實現了資料與操作的初步封裝,是邁向物件導向思維的關鍵一步。
| 版本 | 資料結構 | 適用場景 | 擴充性 |
|---|---|---|---|
| 一維陣列 | float[] | 單一科目、定長 | 低 |
| 二維陣列 | float[][] | 多科目、固定人數 | 中 |
| 指標 | float* | 動態記憶體、函數傳遞 | 中高 |
| 結構體 | struct[] | 多欄位、真實業務 | 高 |
實務開發中,建議結合結構體 + 動態記憶體配置 + 鏈結串列/動態陣列,並將各功能拆分為獨立模組(.c/.h),才能構建可維護、可擴充的管理系統。