核心知識點
- 結構體定義與陣列聲明
- 指針遍歷結構體陣列
- 冒泡排序實現分數降序排列
- 指針算術與成員存取(
-> / .)
原始代碼問題分析
- 列印函式錯誤:
printf("%d student scored is %0.2f\n", i+1, p[i]) 傳入整個結構體而非 p[i].score,導致未定義行為。
- 排序邏輯缺陷:雙層迴圈邊界錯誤(
i<4; j<5),且交換邏輯會破壞資料完整性;正確冒泡排序應為 j<n-1-i。
- 步長錯誤:列印迴圈
i+=2 導致漏輸出偶數索引學生。
修正優化版完整代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char number[15];
float score;
} Student;
// 列印所有學生資料
void print_students(Student *stu, int n) {
for (int i = 0; i < n; i++) {
printf("Student %d: ID=%s, Score=%.2f\n", i+1, stu[i].number, stu[i].score);
}
}
// 分數降序排序(冒泡排序優化版)
void sort_by_score_desc(Student *stu, int n) {
for (int i = 0; i < n-1; i++) {
int swapped = 0;
for (int j = 0; j < n-1-i; j++) {
if (stu[j].score < stu[j+1].score) {
Student tmp = stu[j];
stu[j] = stu[j+1];
stu[j+1] = tmp;
swapped = 1;
}
}
if (!swapped) break; // 提前結束優化
}
}
// 查找最高分學生(排序後首元素即為最高分)
void find_top_student(Student *stu, int n) {
if (n <= 0) return;
sort_by_score_desc(stu, n);
printf("Top Student: ID=%s, Score=%.2f\n", stu[0].number, stu[0].score);
}
int main() {
Student class[5] = {
{"121", 88.8}, {"122", 77.7}, {"123", 48.4},
{"124", 99.1}, {"125", 78.3}
};
int n = 5;
printf("--- Original Data ---\n");
print_students(class, n);
printf("\n--- Sorted by Score (Desc) ---\n");
sort_by_score_desc(class, n);
print_students(class, n);
printf("\n--- Highest Score ---\n");
find_top_student(class, n); // 此處會再次排序,實際可直接用排序後結果
return 0;
}
關鍵改進解析
| 原始問題 | 修正方案 | 原理 |
| 列印傳遞結構體值 | 改為 stu[i].score | %f 對應 float,結構體不可直接列印 |
| 排序邊界與邏輯錯誤 | 標準冒泡排序 j < n-1-i + 交換旗標優化 | 減少不必要比較,確保每輪將最大值冒泡到末尾 |
| 硬編碼陣列大小 | 引入 n 參數傳遞長度 | 提升函式通用性,避免魔術數字 |
使用 system("pause") | 移除,改用標準輸入等待或直接返回 | 跨平台相容,避免安全風險 |
進階擴展建議
- 動態記憶體:使用
malloc/realloc 實現可變長度學生名單。
- 多鍵排序:分數相同時按學號升序,使用
qsort + 自定義比較函式。
- 檔案持久化:將結構體陣列二進位寫入檔案(
fwrite),支援斷點續存。
- 鏈表實現:將陣列改為單向鏈表,練習指針操作與記憶體管理。