C 語言處理字符串數組輸入排序是經典練習,但 gets() 不安全、未分配內存直接寫入導致崩潰是新手雙重陷阱。本文提供安全、標準的完整實現。
char *name[5] 僅分配 5 個指針,指向隨機地址gets():無緩衝區長度檢查,極易緩衝區溢出,C11 標準已移除input() 邏輯錯:gets(name) 嘗試向指針數組首地址寫入,而非逐個字符串
#include
#include
#include
#define MAX_NAMES 5
#define MAX_LEN 100
void input(char *names[], int n) {
for (int i = 0; i < n; i++) {
// 1. 為每個字符串分配堆內存
names[i] = (char *)malloc(MAX_LEN * sizeof(char));
if (!names[i]) {
fprintf(stderr, "內存分配失敗\n");
exit(1);
}
// 2. 使用 fgets 安全讀取 (包含換行符)
printf("請輸入第 %d 個字符串: ", i + 1);
if (fgets(names[i], MAX_LEN, stdin) == NULL) {
names[i][0] = '\0';
} else {
// 3. 移除末尾換行符
size_t len = strlen(names[i]);
if (len > 0 && names[i][len - 1] == '\n') {
names[i][len - 1] = '\0';
}
}
}
}
void sort(char *names[], int n) {
for (int i = 0; i < n - 1; i++) {
int k = i;
for (int j = i + 1; j < n; j++) {
if (strcmp(names[k], names[j]) > 0) { // 字典序升序
k = j;
}
}
if (k != i) {
char *temp = names[i];
names[i] = names[k];
names[k] = temp;
}
}
}
void print(char *names[], int n) {
printf("\n排序結果:\n");
for (int i = 0; i < n; i++) {
printf("%s\n", names[i]);
}
}
void freeNames(char *names[], int n) {
for (int i = 0; i < n; i++) {
free(names[i]); // 釋放每個字符串內存
names[i] = NULL;
}
}
int main() {
char *names[MAX_NAMES] = {NULL};
input(names, MAX_NAMES);
sort(names, MAX_NAMES);
print(names, MAX_NAMES);
freeNames(names, MAX_NAMES); // 關鍵:釋放內存
return 0;
}
| 環節 | 錯誤做法 | 正確做法 | 原因 |
|---|---|---|---|
| 內存分配 | 無分配 | malloc 為每串分配 | 指針需指向有效內存 |
| 輸入函數 | gets() | fgets(buf, size, stdin) | 防緩衝區溢出,C11 標準 |
| 換行符處理 | 忽略 | 檢查並替換 \n 為 \0 | fgets 保留換行符 |
| 排序比較 | 直接比較指針 | strcmp 比較內容 | 指針地址無序關係 |
| 內存釋放 | 無 | 循環 free() | 防內存洩漏 |
// 使用 realloc 支持任意長度輸入
char **names = NULL;
int capacity = 0, count = 0;
char line[MAX_LEN];
while (fgets(line, MAX_LEN, stdin)) {
if (count >= capacity) {
capacity = capacity ? capacity * 2 : 4;
names = realloc(names, capacity * sizeof(char*));
}
line[strcspn(line, "\n")] = '\0'; // 移除換行
names[count] = strdup(line); // 分配並複製
count++;
}
// 排序、打印...
for (int i = 0; i < count; i++) free(names[i]);
free(names);
掌握 malloc/fgets/strcmp/free 組合拳,是 C 語言字符串處理的基本功。