時隔多年重拾 C 語言,首戰 HDU 2001「計算兩點間的距離」。本文記錄從輸出超限(Output Limit Exceeded)到 Accepted 的完整排查過程,深度剖析 scanf 格式匹配機制、浮點數讀取陷阱、EOF 循環邊界條件,並附贈英語學習筆記「first day」vs「at the first day」辨析。
x1 y1 x2 y2,空格分隔0 0 0 1 → 1.00,0 1 1 0 → 1.41#include <stdio.h>
#include <math.h>
int main() {
int x1, y1, x2, y2; // 錯誤:用 int 讀取實數
double result;
while (scanf("%d %d %d %d", &x1, &y1, &x2, &y2) != EOF) {
result = sqrt((y2-y1)*(y2-y1) + (x2-x1)*(x2-x1));
printf("%.2f\n", result);
}
return 0;
}
%d 讀 intscanf 遇到小數點 . 時匹配失敗,不消費該字符,導致死循環反覆讀取同一失敗位置#include <stdio.h>
#include <math.h>
int main() {
double x1, y1, x2, y2, result; // 正確:double 對應 %lf
while (scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2) != EOF) {
result = sqrt((y2-y1)*(y2-y1) + (x2-x1)*(x2-x1));
printf("%.2lf\n", result); // printf 中 %f/%lf 通用,%lf 語義更清晰
}
return 0;
}
| 場景 | 行為 | 返回值 | 輸入流狀態 |
|---|---|---|---|
| 格式匹配成功 | 賦值、消費字符 | 成功項數 | 指向下一字符 |
| 格式匹配失敗 | 不賦值、不消費字符 | 已成功項數 | 停留在失敗字符 |
| 遇到 EOF | 無賦值 | EOF (-1) | 流結束 |
黃金法則: 輸入數據類型決定 scanf 格式符。實數必須用 %lf(double)或 %f(float),絕不能用 %d。
// 標準模式:檢查返回值 == 期望項數
while (scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2) == 4) {
// 處理邏輯
}
// 等價於 != EOF 但語義更精確:只有 4 項全讀成功才進循環體
兩點 (x1,y1), (x2,y2) 歐幾里得距離:
double dx = x2 - x1; double dy = y2 - y1; double dist = sqrt(dx*dx + dy*dy); // 需 #include並鏈接 -lm
編譯提示: GCC 需顯式鏈接數學庫 gcc main.c -o main -lm。
| 表達 | 語法角色 | 典型語境 | 中文語感 |
|---|---|---|---|
| first day | 名詞短語 | My first day was great. | 第一天(作主語/賓語) |
| at the first day | 介詞短語作狀語 | At the first day, I felt nervous. | 在第一天(句首/句尾) |
| on the first day | 介詞短語作狀語 | On the first day of school... | 在第一天(更地道,用 on 表示具體某天) |
| the first day | 特定指代 | I remember the first day. | 那第一天(雙方都知道哪一天) |
寫作建議: 獨立句子用 My first day...;時間狀語首選 On the first day...;避免句首用 At the first day(語感生硬)。
scanf 格式符必須與變量類型精確匹配,失敗不消費字符是死循環禍首-lm 鏈接數學庫,VS Code + C/C++ Extension 調試重拾 C 語言的第一天,沒有華麗的語法糖,只有對輸入輸出機制最樸素的敬畏。每一次 OLE、WA、RE 都是在向機器確認:「我真正理解你的語言了嗎?」