成績排序時,對應姓名也要同步交換。原碼用二維陣列 STR names[] 存姓名,交換需 strcpy 易越界且慢。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_N 256
#define NAME_LEN 32
int main() {
int n;
printf("人數: "); scanf("%d", &n); getchar();
float *score = malloc(n * sizeof(float));
char **name = malloc(n * sizeof(char*));
for (int i = 0; i < n; i++) {
name[i] = malloc(NAME_LEN);
printf("姓名 %d: ", i+1); fgets(name[i], NAME_LEN, stdin);
name[i][strcspn(name[i], "\n")] = 0; // 去換行
printf("成績 %d: ", i+1); scanf("%f", &score[i]); getchar();
}
// 冒泡排序:同時交換 score 指標與 name 指標
for (int i = 0; i < n-1; i++)
for (int j = 0; j < n-1-i; j++)
if (score[j] < score[j+1]) {
float tmpS = score[j]; score[j] = score[j+1]; score[j+1] = tmpS;
char *tmpN = name[j]; name[j] = name[j+1]; name[j+1] = tmpN;
}
printf("\n排序後:\n");
for (int i = 0; i < n; i++)
printf("%-10s %.1f\n", name[i], score[i]);
// 釋放記憶體
for (int i = 0; i < n; i++) free(name[i]);
free(name); free(score);
return 0;
}
| 原碼問題 | 改進 |
|---|---|
STR name[] 固定二維陣列 | char **name 指針陣列,交換僅搬移 8 位元組指標 |
gets 不安全 | fgets + 去換行,防緩衝區溢出 |
malloc 未檢查 | 實戰需檢查回傳值 |
| 排序函數僅排成績 | 雙陣列同步交換,邏輯內聚 |
typedef struct { char name[NAME_LEN]; float score; } Student;
Student *arr = malloc(n * sizeof(Student));
// 排序時交換整個 Student 結構體 (memcpy 或直接賦值)
結構體法語意更清晰,現代編譯器優化後效能相當。