現象:輸入幾個字母按 Enter 程式崩潰
#include <stdio.h>
int main(void) {
char a;
scanf("%s", &a); // ❌ 災難性錯誤
printf("%s", a); // ❌ 格式化字串不匹配
getchar();
return 0;
}
三大錯誤解析
char a 只能存一個字元,%s 會讀取一個「字串」(遇空白停止),並自動在末尾加 \0,至少需要 2 位元組。寫入單一 char 會覆蓋鄰近記憶體 → 緩衝區溢位 → 未定義行為(崩潰、靜默資料破壞)。
scanf("%s", &a) 傳址型別錯誤:%s 期望 char*,&a 是 char* 剛好型別吻合,但指向單一字元,空間不足。
printf("%s", a) 將字元值當指標:%s 期望 char*,傳入 char 會被解讀為位址 → 存取違規。
修正版:使用陣列 + 寬度限制
#include <stdio.h>
#define MAX_LEN 31
int main(void) {
char buf[MAX_LEN + 1] = {0}; // +1 留給 \0
printf("請輸入字串(最多 %d 字元):", MAX_LEN);
if (scanf("%31s", buf) == 1) { // %31s 限制讀取長度,防止溢位
printf("你輸入的是:%s\n", buf);
} else {
printf("讀取失敗或輸入為空。\n");
}
// 清理殘留換行符
int c;
while ((c = getchar()) != '\n' && c != EOF);
return 0;
}
進階:讀取整行(含空白)
char line[256];
if (fgets(line, sizeof(line), stdin)) {
line[strcspn(line, "\n")] = '\0'; // 移除尾部換行
printf("整行內容:%s\n", line);
}
關鍵口訣
char ≠ 字串,**字串 = char 陣列 + \0 結尾**。
scanf("%s", ...) **永遠加寬度限制**(如 %31s)。
- 輸入含空白 → 用
fgets 或 getline(POSIX)。