問題現象
使用者編寫的加減法測試系統,答完 10 題後詢問「是否再一次答題?」,輸入 'y' 應重新開始,但程式直接結束。
錯誤代碼定位
printf("\n是否再一次答題?是(y)/否(n)\n");
scanf(" %c", &k);
if (k == 'n')
printf("歡迎下次使用~^_^~\n");
break; // ← 錯誤位置:不在任何迴圈/switch 中!
錯誤分析
| 問題 | 說明 |
| break 位置錯誤 | break 必須在 for/while/do-while/switch 內部,此處獨立存在導致編譯錯誤或未定義行為 |
| 邏輯結構混淆 | 外層 while(k=='y') 應控制「重新答題」,但 break 打破結構 |
| 縮排誤導 | 錯誤的縮排讓人誤以為 break 屬於 if 或 while |
修正方案
方法一:移除 break,利用迴圈條件自然控制
int main() {
char start = 'n';
char again = 'y';
// 歡迎畫面...
printf("準備好了嗎?是(y)/否(n)\n");
scanf(" %c", &start);
if (start == 'y') {
while (again == 'y') { // 外層迴圈控制「再玩一次」
// 10 題答題邏輯...
int sum = 0;
for (int num = 1; num <= 10; num++) {
// 出題、判分邏輯...
}
// 顯示總分、評語...
// 詢問是否再玩
printf("\n是否再一次答題?是(y)/否(n)\n");
scanf(" %c", &again); // 更新 again,迴圈條件自動判斷
}
printf("歡迎下次使用~^_^~\n");
} else {
printf("歡迎下次使用~^_^~\n");
}
return 0;
}
方法二:do-while 結構(至少執行一次)
char again = 'y';
do {
// 完整 10 題流程...
printf("\n是否再一次答題?是(y)/否(n)\n");
scanf(" %c", &again);
} while (again == 'y');
printf("歡迎下次使用~^_^~\n");
關鍵修正點總結
| 原始問題 | 修正後 |
break 游離在迴圈外 | 移除 break,用迴圈條件變數 again 控制 |
k 同時用於「開始」與「繼續」 | 分離 start(開始確認)與 again(重玩控制) |
srand((int)time(0)) 在迴圈內 | 移至 main 開頭只呼叫一次,否則同一秒內重複隨機數 |
| 分數累加邏輯在迴圈外 | sum 初始化應在外層迴圈內(每輪重置) |
完整修正版核心架構
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand((unsigned)time(NULL)); // 只初始化一次!
char start;
printf("歡迎使用加減法測試系統\n準備好了嗎?(y/n): ");
scanf(" %c", &start);
if (start != 'y' && start != 'Y') {
printf("再見!\n");
return 0;
}
char again = 'y';
while (again == 'y' || again == 'Y') {
int sum = 0; // 每輪重置分數
int scores[4] = {10, 7, 5, 0};
for (int q = 1; q <= 10; q++) {
int a = rand() % 49 + 1;
int b = rand() % 49 + 1;
int op = rand() % 2; // 0:加, 1:減
int answer, user_ans;
int attempts = 0;
if (op == 0) { answer = a + b; printf("\n第%d題: %d+%d=?", q, a, b); }
else { if (a < b) { int t=a; a=b; b=t; } answer = a - b; printf("\n第%d題: %d-%d=?", q, a, b); }
while (attempts < 3) {
scanf("%d", &user_ans);
if (user_ans == answer) {
sum += scores[attempts];
printf("正確!得 %d 分\n", scores[attempts]);
break;
} else {
attempts++;
if (attempts < 3) printf("錯誤,再試一次: ");
}
}
if (attempts == 3) printf("正確答案: %d\n", answer);
}
printf("\n總分: %d\n", sum);
if (sum > 90) printf("優秀!\n");
else if (sum > 80) printf("良好\n");
else if (sum > 60) printf("及格,繼續加油\n");
else printf("需加強練習\n");
printf("\n再玩一次?(y/n): ");
scanf(" %c", &again);
}
printf("歡迎下次使用!\n");
return 0;
}
學習重點
- break/continue 只能用在迴圈/switch 內:這是語法硬性規定
- 迴圈控制變數要語義清晰:
again 專門控制「重複」,別混用
- srand 只呼叫一次:放在
main 開頭,避免同秒重複序列
- 縮排要誠實反映邏輯層級:錯誤縮排是 Bug 溫床
- 變數作用域最小化:
sum、attempts 等放在需要的迴圈層級內