原始錯誤代碼
#include
main() {
int a, b, c, d, s;
printf("enter: a b c d");
scanf("%f,%f,%f,%f", &a, &b, &c, &d); // 錯誤 1
s = 2(b*c - a*d) / (d*d*c - c*c*d); // 錯誤 2, 3
printf("%f\n", s); // 錯誤 4
}
四大錯誤分析與修正
| # | 錯誤代碼 | 問題 | 修正 |
| 1 | scanf("%f,%f,%f,%f", &a, &b, &c, &d) | 變數為 int,格式應為 %d。%f 對應 float*,寫入位元模式錯誤導致數值亂碼 | scanf("%d,%d,%d,%d", &a, &b, &c, &d) |
| 2 | 2(b*c - a*d) | C 語言不支援隱性乘法。數字緊接括號視為函式呼叫,2(...) 嘗試呼叫位址 2 的函式 → 編譯錯誤/運行崩潰 | 2 * (b*c - a*d) 明確加上 * |
| 3 | 整數除法截斷 | int / int 結果為 int,小數部分直接捨棄。如 5/2 = 2 而非 2.5 | 變數改 float/double,或強制轉型 (float)分子/分母 |
| 4 | printf("%f\n", s) | s 為 int,%f 期望 double,讀取錯誤位元模式 → 輸出亂碼 | printf("%d\n", s) 或 printf("%f\n", (float)s) |
完整修正版
#include
int main() {
// 建議使用浮點數進行精確計算
double a, b, c, d, s;
printf("請輸入 a, b, c, d (以逗號分隔): ");
// 格式字串逗號需與輸入完全對應,建議加空格容錯
if (scanf("%lf,%lf,%lf,%lf", &a, &b, &c, &d) != 4) {
printf("輸入格式錯誤\n");
return 1;
}
double denominator = d*d*c - c*c*d;
if (denominator == 0) {
printf("分母為零,無法計算\n");
return 1;
}
s = 2.0 * (b*c - a*d) / denominator;
printf("結果 s = %.6f\n", s);
return 0;
}
執行測試
請輸入 a, b, c, d (以逗號分隔): 1,2,3,4
結果 s = -0.166667
關鍵知識點總結
scanf 格式字串對照表
| 型別 | scanf 格式 | printf 格式 | 備註 |
| int | %d | %d | 有號十進制 |
| unsigned int | %u | %u | 無號十進制 |
| float | %f | %f | printf 實際接收 double |
| double | %lf | %f | scanf 需 %lf 区分 |
| char | %c | %c | 單字元 |
| char* | %s | %s | 字串,遇空白停止 |
| 長整數 | %ld | %ld | long |
| 長長整數 | %lld | %lld | long long |
| 指標 | %p | %p | 位址十六進制 |
輸入格式容錯建議
// 原始:scanf("%f,%f,%f,%f", ...) 必須輸入 "1,2,3,4"
// 改進:scanf("%lf , %lf , %lf , %lf", ...) 允許 "1, 2, 3, 4" 或 "1 ,2 ,3 ,4"
// 更好:用 fgets 讀整行,再用 sscanf/strtok 解析,完全控制格式容錯
除零保護模式
double denominator = ...;
if (fabs(denominator) < 1e-12) { // 浮點數不直接比較 == 0
printf("分母過小,視為零\n");
return 1;
}
避坑檢查清單
- [ ] 所有
scanf 格式字串與變數型別完全對應
- [ ] 所有除法運算檢查分母非零
- [ ] 需要小數結果的變數宣告為
float/double
- [ ]
printf 格式字串與實參型別、個數、順序一致
- [ ] 所有
scanf 檢查回傳值(成功轉換的項目數)
- [ ] 明確寫出乘法運算子
*,不依賴隱性乘法