統測資電類・資訊科專業科目(二)核心考點

第 5 章:迴圈控制(for/while/do-while)

本章統整統測程式設計中「重複結構」的三大工具:for、while、do-while,以及 break/continue 的追蹤技巧(111~115 年共計 8 題考古真題,是單章題數最多的章節之一)。 出題老師最愛把「unsigned 計數器溢位」、「continue 跳過遞增」、「變數遮蔽」與「巢狀迴圈逐輪追蹤」揉合在一起設計陷阱。 本教學將帶你掌握清晰的逐輪追蹤表格技巧,並透過8 題真題 + 5 題模擬題的所有選項深度剖析,徹底掃除所有答題盲點!

🔁
7 大核心
迴圈控制觀念全解構
🎯
8 題真題
111~115 統測題全收錄
💡
全選項剖析
A/B/C/D 逐項深入拆解
🚀
100% 互動
點擊即答 + 展開詳解

1 三種迴圈的本質與選用時機(for/while/do-while)

三種迴圈做的事情本質上都一樣——「重複執行一段程式碼」,差別只在什麼時候檢查要不要繼續。可以想成三種不同的用餐習慣:

迴圈白話比喻判斷時機最少執行次數
for 已經知道要繞操場跑幾圈,直接設定圈數 先判斷,條件包含在迴圈標頭裡 0 次(次數已知時通常不會是0,但條件一開始就不成立時可以是0)
while 檢查郵筒,有信才拿,沒信就不開箱 先判斷條件,條件為假就完全不進入 0 次
do-while 自助餐先夾一口菜試吃,吃完才決定要不要繼續夾 先執行本體,執行完才判斷條件 1 次(不管條件一開始是真是假,本體一定會先跑一次)
C Code:三種迴圈達到相同結果(印出 1~5)
#include <stdio.h>
int main(void) {
    int i;

    // for:已知要跑5次
    for (i = 1; i <= 5; i++) printf("%d ", i);
    printf("\n");

    // while:先判斷才做
    i = 1;
    while (i <= 5) { printf("%d ", i); i++; }
    printf("\n");

    // do-while:先做才判斷(本題條件一開始就成立,效果與while相同)
    i = 1;
    do { printf("%d ", i); i++; } while (i <= 5);
    printf("\n");

    return 0;
}
🖥️ 終端機執行輸出結果
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
💡 怎麼選?

次數明確(跑N次、走訪陣列每個元素)→ 優先用 for;次數不確定、但知道停止條件(讀到檔案結尾、使用者輸入0才停)→ 用 while;必須先做一次才能判斷(先讀一次輸入才知道要不要繼續讀)→ 用 do-while。

2 for 迴圈語法拆解與執行順序

for(初始化; 條件; 遞增) 三段式寫法最容易讓人誤會執行順序。真正的執行順序是:

  1. 初始化——只執行一次,用來設定迴圈變數的起始值。
  2. 條件判斷——每一輪開始前都會檢查,為假就直接結束整個迴圈。
  3. 執行本體——條件為真才執行大括號裡的程式碼。
  4. 遞增/遞減——本體執行完後才做,接著回到步驟2重新判斷條件。
C Code:逐輪追蹤 for 迴圈(統測111年Q43示範)
int i, total = 0;
for (i = 1; i < 8; i += 2)
    total += i;
// i依序為 1、3、5、7(每次遞增2)
// total累加:0+1+3+5+7 = 16
// i變9時,9<8不成立,迴圈結束
輪次條件判斷(i<8)執行本體 total+=i本體結束後 i+=2
11<8 → 真total=0+1=1i變3
23<8 → 真total=1+3=4i變5
35<8 → 真total=4+5=9i變7
47<8 → 真total=9+7=16i變9
59<8 → 假,結束(不執行)—
⚠️ 邊界值陷阱:< 與 <= 只差一個等號

寫成 i < 8 跟 i <= 8 在遞增規律剛好卡在邊界時會產生不同的總輪數。逐輪手動列表追蹤(如上表)是最保險的做法,不要只憑直覺猜輪數。

3 while 與 do-while 的關鍵差異:先判斷 vs 先執行

兩者的差異只在「檢查條件」與「執行本體」誰先誰後,但這個順序在條件一開始就是假的情況下,會讓兩者的執行次數完全不同:

C Code:條件一開始就是假時的關鍵差異
int n = 5, count = 0;

while (n < 3) {       // 5<3為假,本體一次都不會執行
    count++;
    n--;
}
printf("while: count=%d\n", count); // 輸出 0

n = 5; count = 0;
do {                   // 不管條件,先執行一次
    count++;
    n--;
} while (n < 3);        // 執行後n=4,4<3為假,結束
printf("do-while: count=%d\n", count); // 輸出 1
🖥️ 終端機執行輸出結果
while: count=0
do-while: count=1
⚠️ 常考陷阱:變數遮蔽(shadowing)讓「修改」失效

統測 112 年 Q46 出過一題:全域變數 int x = 100; 與 main() 內的區域變數 int x = 0; 同名。一旦函式內重新宣告了同名變數,這個區域變數會遮蔽(shadow)外層的全域變數,函式內所有用到 x 的地方都是指這個區域變數。這種情況下,不管怎麼修改全域 x 的初始值,對函式內的行為都完全沒有影響。

🧠 另一個常考陷阱:do-while 本體內先被覆蓋的初始值是「死值」

如果 do-while 本體的第一行就是 y = 某運算式;,那麼 y 宣告時的初始值在第一次比較條件之前早就已經被覆蓋,不管原本設定成什麼都不會影響任何一輪的判斷結果——跟第4章「flag 初始值被覆蓋」是同一種陷阱的迴圈版本。

4 break 與 continue 的差異與追蹤技巧

break 是「立刻、完全結束整個迴圈」;continue 只是「跳過這一輪剩下的程式碼,回到條件判斷繼續下一輪」。兩者效果差很多,追蹤程式時務必分清楚。

C Code:break 跳出整個迴圈、continue 只跳過本次
#include <stdio.h>
int main(void) {
    for (int i = 1; i <= 10; i++) {
        if (i % 2 == 0) continue;  // 偶數:跳過本次,不印
        if (i > 7) break;          // 大於7:整個迴圈直接結束
        printf("%d ", i);
    }
    printf("\n"); // 輸出: 1 3 5 7
    return 0;
}
🖥️ 終端機執行輸出結果
1 3 5 7
⚠️ 最危險的陷阱:continue 在 while 迴圈裡會跳過「手動寫的遞增」

在 for 迴圈裡,continue 只會跳過本體剩下的程式碼,迴圈標頭的遞增運算式(如 i++)依然會照常執行。但在 while 迴圈裡,如果遞增變數是寫在本體最後一行(例如 i++;),continue 會連這行遞增也一起跳過!這會讓迴圈卡在同一個索引,重複比對同一個位置,統測 115 年 Q40 就是靠這個陷阱設計出「同一個位置被多算一次」的追蹤題。

5 巢狀迴圈(nested loop)執行次數推算與逐輪追蹤

巢狀迴圈就是「迴圈裡面還有迴圈」:外層迴圈每跑一輪,內層迴圈就會完整地從頭跑到尾一次。

C Code:巢狀迴圈印出九九乘法表片段
#include <stdio.h>
int main(void) {
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= 3; j++)
            printf("%d*%d=%d  ", i, j, i * j);
        printf("\n");
    }
    return 0;
}
// 外層3次、內層3次,總共執行 3×3=9 次乘法運算
💡 手動追蹤巢狀迴圈的訣竅:畫「外層輪次 → 內層完整跑一次」的表格

遇到巢狀迴圈題目,不要只憑直覺猜總執行次數,養成習慣列一張表:外層第幾輪、這一輪內層變數從哪裡跑到哪裡、這一輪對總結果貢獻了多少。尤其當內層迴圈的起始值或上限依賴外層變數時(例如 for(j=i; j<=5; j++)),每一輪外層迴圈內層實際跑的次數都不一樣,更需要逐輪列出來確認,不能套用固定次數。

🧠 常見誤解:以為 sum 之類的累加變數會在每輪外層迴圈重設

只要累加變數(如 sum、total)是宣告在最外層迴圈之外,它就會持續累加每一輪外層與內層迴圈的貢獻,不會在外層迴圈的每一輪開始時被重設歸零。這是巢狀迴圈追蹤題最常見的失分點之一。

6 迴圈計數器溢位陷阱:unsigned 導致無窮迴圈(統測最愛的坑)

這是本章統測命中率最高的觀念!如果迴圈計數器被宣告為 unsigned(不含符號,只能表示0與正數),當它遞減到 0 以後再減1,並不會變成 -1,而是會整數溢位、環繞(wrap around)成該型態能表示的最大正數,導致「i >= 0」這種條件永遠為真,形成無窮迴圈。

C Code:unsigned 計數器遞減導致無窮迴圈
unsigned short i;
for (i = 5; i >= 0; i--) {   // 危險!i是unsigned,永遠 >= 0
    printf("%d ", i);
}                            // i從0再減1不會變成-1,而是環繞成65535 → 無窮迴圈
型態可表示範圍0 再減 1 的結果
short(有號)-32768 ~ 32767-1(正常遞減)
unsigned short0 ~ 65535環繞成 65535(絕不會變負數)
unsigned char0 ~ 255環繞成 255
⚠️ 這種 bug 比編譯錯誤更危險

把計數器宣告為 unsigned 完全不會造成編譯錯誤,程式可以正常編譯、正常執行前幾輪,只有在計數器真的遞減穿越 0 的那一刻才會出事——這正是它危險的原因:平常測試時如果剛好沒有觸發到邊界,這個 bug 很容易被忽略,直到上線後才爆發。

🧠 記憶口訣

「unsigned 沒有負的家,減到底只會繞回來」——看到迴圈計數器宣告成 unsigned,且迴圈條件用 >= 0 搭配遞減,要立刻提高警覺檢查會不會無窮迴圈。

7 迴圈實務應用:陣列走訪步伐與字串走訪終止條件

迴圈最常見的實務用途就是走訪陣列與字串。這裡整理兩個統測愛考的實務技巧:

技巧一:用 for 迴圈的遞增步伐(step)跳著讀陣列

for(i=0; i<n; i+=2) 每次跳2格,可以只讀取陣列中偶數索引的元素,常用來在一組「正確資料+干擾資料」交錯排列的陣列中,只挑出真正需要的那些元素。

C Code:跳著讀陣列,濾掉交錯排列的干擾資料
char S[9][4] = {"沖","收","脫","蓋","泡","沖","蓋","脫","送"};
// 索引:0=沖 1=收(干擾) 2=脫 3=蓋(干擾) 4=泡 5=沖(干擾) 6=蓋 7=脫(干擾) 8=送
for (int i = 0; i < 9; i += 2)
    printf("%s", S[i]);
// 只印出索引0,2,4,6,8:沖脫泡蓋送(正確的燒燙傷急救步驟)

技巧二:用 while 迴圈走訪字串,直到遇見 '\0'

C 語言字串以 '\0'(空字元)作為結尾標記,走訪字串常寫成 while(str[i] != '\0'),代表「還沒走到結尾就繼續」。比對兩個長度不同的字串時,常用 || 讓迴圈跑到兩個字串都走到結尾才停止:

C Code:以 || 讓迴圈跑到兩個字串都結束為止
int i = 0;
char a[] = "abc#123456*789";  // 長度14
char b[] = "cba#987654*321";  // 長度14
while (a[i] != '\0' || b[i] != '\0') {
    // 只要任一個字串在這個位置還沒結束,就繼續比對
    i++;
}
⚠️ 陷阱:迴圈本體裡如果用 continue「跳過」i++,位置就卡住了

結合第4節的陷阱:如果 i++ 是寫在 while 本體最後一行、而本體中間又有 continue,一旦觸發 continue,這一輪的 i++ 就不會執行,下一輪會重新比對同一個索引位置。這在字串比對類的追蹤題中是失分率最高的細節。

8 111~115 歷屆統測真題全選項深度剖析(共 8 題)

以下收錄統測專業科目(二)近年全部 8 題迴圈控制(for/while/do-while)真題。每題均提供高解析度原始考題掃描圖、互動選項按鈕與所有選項逐項深入解析:

111 統測專二 Q43 📌 概念:for 迴圈遞增步伐與累加追蹤
試題來源:技專校院入學測驗中心
下列 C 語言程式碼片段執行結果,變數 total 的值為何?
題幹程式碼
int i, total=0;
for(i=1; i<8; i+=2)
    total+=i;
111 統測專二 Q43 題目截圖
本題標準答案: (C) 16

🔍 四個選項逐項深度剖析

選項 A(4)錯誤解析
此答案可能只手動追蹤了兩輪迴圈(i=1、i=3)就以為已經滿足結束條件,1+3=4,忽略了 i=5、i=7 時「5<8」與「7<8」其實都還成立,迴圈實際上會跑滿4輪,不是2輪。
選項 B(8)錯誤解析
此答案可能把「i 每次遞增2」誤記成「total 每次固定加2」,而不是把當下的 i 值累加進 total,於是誤算成每輪固定加2、共4輪等於8,忽略了程式碼寫的其實是 total+=i——要累加的是 i 本身當下的值,不是遞增的步伐量。
正確答案完整推導(★ 本題標準答案)
i 依序為 1、3、5、7(每次遞增2)。total 逐輪累加:0+1=1,1+3=4,4+5=9,9+7=16。當 i 變成9時,9<8不成立,迴圈結束,total=16,選 (C)。
選項 D(28)錯誤解析
此答案是把 i+=2(每次遞增2)誤看成 i++(每次只遞增1)的典型結果——若 i 真的逐一遞增為1,2,3,4,5,6,7,total 會變成1+2+3+4+5+6+7=28。這提醒我們必須看清楚遞增運算式寫的到底是 +=1 還是 +=2,不能只看到「i 在遞增」就直接假設是逐一加1。
111 統測專二 Q44 📌 概念:while 迴圈/輾轉相除法(GCD)追蹤
試題來源:技專校院入學測驗中心
下列 C 語言程式碼片段執行結果,變數 y 的值為何?
題幹程式碼
int y, r, a=30, b=42;
r=a%b;
while(r!=0)
{
    a=b;
    b=r;
    r=a%b;
}
y=b;
111 統測專二 Q44 題目截圖
本題標準答案: (D) 6

🔍 四個選項逐項深度剖析

選項 A(42)錯誤解析
此答案很可能是誤算了初始餘數 r=a%b=30%42,誤以為 a 比 b 小就代表「除不盡、餘數視為0」,讓迴圈條件 r!=0 一開始就被誤判為假,完全跳過迴圈本體,於是 y 直接等於 b 從未被改變過的初始值 42。實際上 30%42 的餘數就是 30 本身(因為30本來就小於42),r!=0 成立,迴圈一定會執行。
選項 B(30)錯誤解析
此答案可能把最後要取的變數搞混,把 y=b; 誤看成 y=a;,並且套用了 a 進入迴圈前的初始值30。但題目寫的明明白白是把 b 的值賦給 y,不是 a。
選項 C(12)錯誤解析
此答案很可能是少追蹤了最後一輪迴圈——當算到第2輪 b 變成12時就誤以為已經結束,忽略了此時 r=30%12... 對,正確算法是a=30,b=12,r=30%12=6,此時 r=6,r!=0 仍然成立,還要再跑一輪(a=12,b=6,r=12%6=0)才會真正結束。
正確答案完整推導(★ 本題標準答案,輾轉相除法求最大公因數)
初始 r=30%42=30(30<42,餘數就是30本身)。第1輪:a=b=42,b=r=30,r=a%b=42%30=12。第2輪:a=b=30,b=r=12,r=a%b=30%12=6。第3輪:a=b=12,b=r=6,r=a%b=12%6=0,r!=0不成立,迴圈結束。y=b=6,選 (D)。這正是計算最大公因數(GCD)的經典演算法。
112 統測專二 Q46 📌 概念:do-while/變數遮蔽(shadowing)/前置與後置遞增
試題來源:技專校院入學測驗中心
曉華發現迴圈內行號8和行號9的程式碼只執行了一次,下列哪一種修改方式可以讓迴圈多執行幾次?(提示:sin(1)=0.8415)
題幹程式碼
#include <stdio.h>
#include <math.h>
int x = 100;
int main(){
    int x = 0;
    double y = 0.0;
    do{
        y = 10*sin(x);
        printf("x=%d, y=%lf\n", x, y);
    } while(++x <= y);
    printf("end of program\n");
    return 0;
}
112 統測專二 Q46 題目截圖
本題標準答案: (B) 把行號10中的 ++x 改為 x++

🔍 四個選項逐項深度剖析

選項 A 錯誤解析
此答案誤以為修改全域變數 x 會影響程式行為,忽略了 main() 內用 int x = 0; 重新宣告了一個同名的區域變數,這個區域 x 會遮蔽(shadow)外層的全域 x,此後函式內所有的 x 都指向這個區域變數,修改全域 x 的初始值不會有任何作用。
正確答案完整推導(★ 本題標準答案)
原本用前置遞增 ++x,每輪比較用的是「已經加1後」的新值,第1輪 x 先變1才比較 1<=0(y此時仍是初始的sin(0)*10=0)為假,只跑1次。改成後置遞增 x++ 後,比較用的是「還沒加1前」的舊值:第1輪 0<=0 真→x變1;第2輪 y=10sin(1)=8.415,1<=8.415 真→x變2;第3輪 y=10sin(2)≈9.09,2<=9.09 真→x變3;第4輪 y=10sin(3)≈1.41,3<=1.41 假,結束,共執行4次。
選項 C 錯誤解析
此答案誤以為 y 的初始值會影響迴圈的判斷次數,但迴圈本體的第一行 y = 10*sin(x); 在第一次比較 ++x<=y 之前就已經先執行過一次,把 y 的值整個覆蓋掉了,因此 y 原本被設定的初始值(不論是0.0還是-1.0)從頭到尾都不會被拿來做真正的比較,是一個「死值」。
選項 D 錯誤解析
與選項A同理,修改的是被區域變數 x 遮蔽掉的全域 x。main() 內實際使用的是 int x = 0; 這個區域宣告,跟全域 x 的初始值完全無關,改了也不會產生任何效果。
114 統測專二 Q41 📌 概念:巢狀迴圈(while+do-while)/布林代數真值表推導
試題來源:技專校院入學測驗中心
下列 C 語言程式可輸出布林代數式 F(A,B) 之真值表,則 F(A,B) 為何?
題幹程式碼
int X=0, Y=0, Z;
printf("%c %c %c\n", 'A', 'B', 'F');
do{
    while(Y<=1){
        Z=((X||!Y)&&(Y||X));
        printf("%d %d %d\n", X, Y, Z);
        Y++;
    }
    Y=0;
    X++;
}while(X<=1);
114 統測專二 Q41 題目截圖
本題標準答案: (D) F(A,B) = (A+B̄)(A+B)

🔍 四個選項逐項深度剖析

選項 A 錯誤解析
化簡 B + AB̄ + AB = B + A(B̄+B) = B + A = A+B(也就是邏輯 OR)。代入 (A,B)=(0,1):A+B=1,但程式實際追蹤出的真值表在 X=0,Y=1 時 Z=0(因為 X||!Y=0||0=0,導致整個 AND 為0),兩者不符,此選項與第2組真值矛盾。
選項 B 錯誤解析
代入 (A,B)=(0,0):A + ĀB̄ + AB = 0 + (1×1) + 0 = 1,但程式追蹤出 X=0,Y=0 時 Z=((0||!0)&&(0||0))=((0||1)&&(0))=(1&&0)=0,兩者不符,此選項與第1組真值矛盾。
選項 C 錯誤解析
化簡 ĀB + AB = B(Ā+A) = B。代入 (A,B)=(1,0):B=0,但程式追蹤出 X=1,Y=0 時 Z=((1||!0)&&(0||1))=((1||1)&&(1))=(1&&1)=1,兩者不符,此選項與第3組真值矛盾。
正確答案完整推導(★ 本題標準答案)
逐一追蹤四組 (X,Y):(0,0)→Z=(0||1)&&(0||0)=1&&0=0;(0,1)→Z=(0||0)&&(1||0)=0&&1=0;(1,0)→Z=(1||1)&&(0||1)=1&&1=1;(1,1)→Z=(1||0)&&(1||1)=1&&1=1。四組結果依序是0,0,1,1,可見 Z 恆等於 X(也就是 F 恆等於 A,跟 B 無關)。代入 (D) 化簡:(A+B̄)(A+B) = A·A + A·B + A·B̄ + B̄·B = A + A(B+B̄) + 0 = A + A = A,與追蹤結果完全相符,選 (D)。
115 統測專二 Q35 📌 概念:迴圈遞增步伐/二維字元陣列走訪
試題來源:技專校院入學測驗中心
在程式行號5裡應置入下列哪一個選項的程式碼,可輸出正確的燒燙傷急救步驟順序?
題幹程式碼
char S[12][4]={"沖","收","脫","蓋","泡","沖","蓋","脫","送"};
void main(void){
    printf("%s",S[i]);
}
115 統測專二 Q35 題目截圖
本題標準答案: (C) for(i=0; i<9; i+=2)

🔍 四個選項逐項深度剖析

選項 A 錯誤解析
for(i=0;i<5;i++) 會依序印出 S[0]~S[4],也就是「沖、收、脫、蓋、泡」——把索引1的干擾資料「收」也印了出來,而且完全沒印到最後的「送」,順序既不完整也混入了假資料。
選項 B 錯誤解析
for(i=1;i<6;i++) 會依序印出 S[1]~S[5],也就是「收、脫、蓋、泡、沖」——起始索引就選錯了(從干擾資料「收」開始),印出的順序完全不對應正確的急救步驟。
正確答案完整推導(★ 本題標準答案)
陣列中索引0,2,4,6,8依序存放「沖、脫、泡、蓋、送」,正是正確的急救步驟順序;索引1,3,5,7(收、蓋、沖、脫)是刻意排入的干擾假資料。要跳過干擾資料、只挑出偶數索引,需要「從0開始、每次加2、跑到8」,也就是 for(i=0;i<9;i+=2),選 (C)。
選項 D 錯誤解析
for(i=1;i<10;i+=2) 會印出 S[1],S[3],S[5],S[7],S[9],也就是「收、蓋、沖、脫」加上索引9(陣列只初始化了9個字串,索引9的內容是空字串),起始索引偏移了1,反而挑中了全部的干擾假資料,完全偏離正確的急救步驟。
115 統測專二 Q40 📌 概念:字串比對/while 迴圈中 continue 跳過遞增的陷阱
試題來源:技專校院入學測驗中心
下列 C 語言程式執行後的輸出結果為何?
題幹程式碼
unsigned short i = 0, c = 0;
char stringA[]="abc#123456*789";
char stringB[]="cba#987654*321";
while(stringA[i]!='\0'||stringB[i]!='\0'){
  if(stringA[i] == stringB[i])
    c++;
  if(c == 3)
    { continue; }
  i++;
}
printf("c=%d", c);
115 統測專二 Q40 題目截圖
本題標準答案: (C) c=5

🔍 四個選項逐項深度剖析

選項 A(c=3)錯誤解析
此答案很可能是把 if(c==3){continue;} 誤讀成 if(c==3){break;},以為第三次比對相符(i=8時 '5'='5')就會讓整個迴圈立刻結束,計數停在3。但程式碼寫的是 continue,只會跳過這一輪剩下的程式碼(也就是跳過 i++;),迴圈並不會結束,後面還有更多字元要繼續比對。
選項 B(c=4)錯誤解析
此答案正確注意到 continue 讓 i=8 這個位置被多比對了一次(c從3變成4),但誤以為迴圈在這之後就結束了,忽略了後面 i=10 時兩個字串都是 '*',還會再相符一次,讓 c 再加1。
正確答案完整推導(★ 本題標準答案)
逐字元比對:i=1('b'='b')c=1;i=3('#'='#')c=2;i=8('5'='5')c=3,觸發 continue,跳過 i++ 直接回到 while 判斷,i 仍為8,再次比對 stringA[8] 與 stringB[8] 仍然相等,c 再加1變成4(此時 c==3 已不成立,不再觸發 continue),i++ 變9;i=9('6'≠'4')不相符;i=10('*'='*')c=5;i=11~13皆不相符;i=14兩字串都走到 '\0',迴圈結束。最終 c=5,選 (C)。
選項 D(c=6)錯誤解析
此答案可能誤以為 i=8 這個位置因為 continue 被重複比對了兩次以上(而不是恰好一次),或是把後面某個原本不相符的位置(例如 i=9 的 '6' 與 '4')誤判成相符,多算了一次,導致總數比正確答案多了1。
115 統測專二 Q41 📌 概念:型態轉換/unsigned 溢位導致無窮迴圈
試題來源:技專校院入學測驗中心
程式無法顯示評價結果,下列程式碼應如何修改?
題幹程式碼
unsigned short sum = 0, i;
int stars[10]={3,5,4,2,1,5,4,0,4,3};
float average = 0.0;
for(i = 9; i >= 0; i--)
  sum+=stars[i];
printf("總評價為 %d 顆星\n", sum);
printf("平均評價為 %.1f 顆星\n", (float)sum/10);
115 統測專二 Q41 題目截圖
本題標準答案: (D) 將行號3程式碼中的 unsigned 刪除

🔍 四個選項逐項深度剖析

選項 A 錯誤解析
這個改法雖然不會再無窮迴圈(i 是遞增到有限上限就停),但引入了新的問題:i<=10 會讓迴圈存取 stars[10],但陣列 stars[10] 只宣告了10個元素、有效索引是0~9,stars[10]是超出陣列範圍的存取;而且從 i=1 開始又漏算了 stars[0],兩個新錯誤加在一起,並不能正確修好這支程式。
選項 B 錯誤解析
這個改法完全沒有解決根本問題:i 依然被宣告為 unsigned short,遞減到0以下時一樣會溢位環繞成一個超大正數,i>=0 依然恆為真,無窮迴圈的問題完全沒有改善;而且起始值 i=10 一開始就會存取超出範圍的 stars[10],反而讓問題更早發作。
選項 C 錯誤解析
把 average 宣告的型態從 float 改成 double,只會影響變數 average 本身的精度,跟迴圈條件、i 的正負號完全無關;即使改了,迴圈依然會因為 unsigned 溢位而無窮迴圈,程式還是跑不到後面的 printf,這個選項改的是不相關的地方。
正確答案完整推導(★ 本題標準答案)
i 被宣告為 unsigned short,其值永遠不會小於0,故 i>=0 恆為真,形成無窮迴圈(i從0再 i-- 會溢位環繞成65535,之後還會持續以超出陣列範圍的巨大索引存取 stars[i]),導致程式跑不到後面的 printf。將 unsigned 刪除,讓 i 變成有號 short,遞減到 -1 時 i>=0 為假,迴圈才能正常結束,選 (D)。
115 統測專二 Q43 📌 概念:巢狀迴圈(while+for)逐輪追蹤
試題來源:技專校院入學測驗中心
下列 C/C++ 語言程式片段執行後,sum 的數值為何?
題幹程式碼
int i, j, sum;
i = 0; sum = 0;
while(i < 5){
  sum = sum + i;
  for(j = i; j <= 5; j++)
    sum = sum + j;
  i = i + 2;
}
115 統測專二 Q43 題目截圖
本題標準答案: (C) 44

🔍 四個選項逐項深度剖析

選項 A(29)錯誤解析
此答案很可能是把內層 for 迴圈的條件 j<=5 誤看成 j<5,導致每一輪內層迴圈都少加了最後一個 j=5 的值:i=0輪內層只加0+1+2+3+4=10;i=2輪內層只加2+3+4=9;i=4輪內層只加4=4;總和=(0+10)+(2+9)+(4+4)=10+11+8=29。三輪剛好都各少加了一次「j=5」,合計少加15(44-29=15),正好等於三輪都漏掉的5×3。
選項 B(38)錯誤解析
此答案很可能是忽略了每輪 while 迴圈開頭那行獨立的 sum = sum + i;,誤以為只有內層 for 迴圈在累加 sum:三輪內層 for 迴圈分別加總15(i=0:0~5)、14(i=2:2~5)、9(i=4:4~5),15+14+9=38。忽略的 sum+=i 三輪合計恰好是0+2+4=6(44-38=6),正好對得上。
正確答案完整推導(★ 本題標準答案)
i=0:sum+=0→sum=0;內層 j=0~5 累加0+1+2+3+4+5=15→sum=15;i變2。i=2(2<5成立):sum+=2→sum=17;內層 j=2~5 累加2+3+4+5=14→sum=31;i變4。i=4(4<5成立):sum+=4→sum=35;內層 j=4~5 累加4+5=9→sum=44;i變6,6<5為假,跳出迴圈。最終 sum=44,選 (C)。
選項 D(50)錯誤解析
此答案的數值非常接近正確答案,最可能的成因是在心算「15+14+9」以及「外層 sum+=i 的 0+2+4」這幾組數字加總時,其中一個步驟的進位或加法算錯,多算了6,導致最終結果從44變成50。這提醒我們巢狀迴圈的手動追蹤題最好逐步寫下每一輪的中間值(如上方推導),而不是憑心算一次算到底,才不容易在加總步驟中出錯。

9 高職段考與模擬精選實戰題(5 題全選項解析)

透過以下 5 題精選模擬試題,全面檢驗你對三種迴圈差異、break/continue、巢狀迴圈與 unsigned 溢位陷阱的掌握度:

模擬實戰第 1 題 📌 概念:for 迴圈遞減步伐與複合賦值運算子方向
已知下列 C 語言程式碼片段,執行後印出的 total 值為何?
C Code
int i, total = 100;
for (i = 10; i > 0; i -= 3)
    total -= i;
printf("%d", total);
本題標準答案: (A) 78

🔍 四個選項逐項深度剖析

正確答案完整推導(★ 本題標準答案)
i 依序為10、7、4、1(每次遞減3;下一個值-2時 -2>0 不成立,迴圈結束)。total 逐輪扣減:100-10=90,90-7=83,83-4=79,79-1=78。最終 total=78,選 (A)。
選項 B(88)錯誤解析
此答案可能誤以為迴圈是從 i=7 開始執行(漏算了第一輪 i=10 這次),只扣掉了7+4+1=12,100-12=88。這反映對 for 迴圈「初始化只執行一次、但迴圈本體從初始值當下就開始跑」不夠熟悉,誤以為要先遞減一次才開始執行本體。
選項 C(79)錯誤解析
此答案可能誤判 i>0 在 i=1 這一輪之前就已經不成立,只扣掉了10+7+4=21,100-21=79,忽略了 i=1 時 1>0 依然成立,這一輪仍然會執行。
選項 D(122)錯誤解析
此答案把 total -= i(減法賦值)誤看成 total += i(加法賦值),符號看反了,算成100+22=122。這是統測最愛考的「複合賦值運算子方向」陷阱——-= 與 += 只差一個符號,代表的運算方向完全相反。
模擬實戰第 2 題 📌 概念:while 與 do-while 在條件一開始為假時的行為差異
已知下列兩段 C 語言程式碼片段各自獨立執行,兩者印出的 count 值分別為何?
C Code
int n = 5, count = 0;
while (n < 3) {
    count++;
    n--;
}
printf("while: count=%d\n", count);

n = 5; count = 0;
do {
    count++;
    n--;
} while (n < 3);
printf("do-while: count=%d\n", count);
本題標準答案: (B) while:0,do-while:1

🔍 四個選項逐項深度剖析

選項 A 錯誤解析
此答案誤以為 do-while 也會像 while 一樣先檢查條件才決定要不要執行,忽略了 do-while 的定義就是「先執行一次本體,才檢查條件」,不管條件一開始是真是假,本體至少都會被執行一次,因此 do-while 的 count 不可能是0。
正確答案完整推導(★ 本題標準答案)
while 在進入迴圈前就先檢查 n<3(5<3為假),本體完全不會執行,count 維持0。do-while 不管條件,先執行一次本體(count變1,n變4),才檢查 4<3(假),迴圈結束,count=1。所以 while:0,do-while:1,選 (B)。
選項 C 錯誤解析
此答案誤以為 while 也會像 do-while 一樣至少執行一次本體,忽略了 while 是「先判斷、條件為假就完全不進入」,本題條件一開始就是假(5<3不成立),while 的本體一次都不會執行,count 必須是0。
選項 D 錯誤解析
此答案把 while 與 do-while 的行為完全對調了——誤以為 while 會保證至少執行一次,而 do-while 才是先判斷條件才決定要不要進入。這正好與兩者的定義相反:do-while 才是「先做才判斷」,while 才是「先判斷才做」。
模擬實戰第 3 題 📌 概念:for 迴圈中 break 與 continue 的追蹤
已知下列 C 語言程式碼片段,執行後印出的 sum 值為何?
C Code
int i, sum = 0;
for (i = 1; i <= 6; i++) {
    if (i == 3) continue;
    if (i == 5) break;
    sum += i;
}
printf("%d", sum);
本題標準答案: (B) 7

🔍 四個選項逐項深度剖析

選項 A(6)錯誤解析
此答案誤以為 continue 在 for 迴圈裡會連迴圈標頭的遞增(i++)也一起跳過,導致 i 卡在3不會變成4,進而少加了 i=4 這一輪。但 for 迴圈的 continue 只跳過本體「剩下的程式碼」,並不會跳過迴圈標頭裡的遞增運算式,i 依然會正常變成4。
正確答案完整推導(★ 本題標準答案)
i=1:sum+=1=1。i=2:sum+=2=3。i=3:觸發 continue,跳過 sum+=3,但迴圈標頭的 i++ 依然照常執行,i變4。i=4:sum+=4=7。i=5:觸發 break,在 sum+=5 之前就整個跳出迴圈。最終 sum=7,選 (B)。
選項 C(11)錯誤解析
此答案誤以為 break 只會跳出「這一層 if」而不是整個迴圈,以為 i=5 那一輪雖然觸發 break,sum+=i 仍然有機會先執行。但 break 的本意就是立刻、完全終止整個迴圈,連同一輪剩下的程式碼(包含 sum+=i)都不會執行。
選項 D(15)錯誤解析
此答案可能誤以為 continue(i==3那次)完全沒有任何效果,讓 i=3 那一輪也正常執行了 sum+=3,只有 break(i==5那次)在真正發生前那一輪仍正常累加:1+2+3+4+5=15。這反映對「continue 會確實跳過本次累加,但迴圈仍會繼續進行下一輪」這件事理解不完整。
模擬實戰第 4 題 📌 概念:巢狀迴圈(內層上限依賴外層變數)逐輪追蹤
已知下列 C 語言程式碼片段,執行後印出的 sum 值為何?
C Code
int i, j, sum = 0;
for (i = 1; i <= 3; i++) {
    for (j = 1; j <= i; j++) {
        sum += j;
    }
}
printf("%d", sum);
本題標準答案: (C) 10

🔍 四個選項逐項深度剖析

選項 A(4)錯誤解析
此答案很可能是把內層迴圈的條件誤看成 j<i(嚴格小於),而不是程式碼實際寫的 j<=i,導致每一輪內層迴圈都少跑最後一次(j=i那次):i=1時內層完全不執行(貢獻0);i=2時只跑j=1(貢獻1);i=3時只跑j=1,2(貢獻3);總和0+1+3=4。
選項 B(6)錯誤解析
此答案很可能誤以為 sum 在每次外層迴圈重新開始時會被重設歸零,只有最後一輪(i=3)內層迴圈累加的1+2+3=6被保留了下來,忽略了 sum 是宣告在最外層迴圈之外、會持續累加每一輪外層迴圈貢獻的變數,並不會中途被重設。
正確答案完整推導(★ 本題標準答案)
i=1時,內層 j=1,sum+=1=1。i=2時,內層 j=1,2,sum+=1+2=3,sum變4。i=3時,內層 j=1,2,3,sum+=1+2+3=6,sum變10。最終 sum=10,選 (C)。這裡的關鍵是內層迴圈的上限 j<=i 會隨外層 i 逐輪增加,而 sum 會持續累加每一輪的貢獻。
選項 D(18)錯誤解析
此答案很可能誤以為內層迴圈的上限固定是 j<=3,而不是隨外層 i 變動的 j<=i,導致誤判每一輪外層迴圈的內層都固定跑3次、加總都是1+2+3=6,三輪外層迴圈總共6+6+6=18,忽略了內層迴圈實際執行的範圍其實會隨外層 i 的值逐輪增加,並不是固定的。
模擬實戰第 5 題 📌 概念:unsigned 計數器遞減溢位導致無窮迴圈
已知下列 C 語言程式碼片段,執行後會發生什麼情況?
C Code
unsigned char i;
for (i = 5; i >= 0; i--) {
    printf("%d ", i);
}
printf("done");
本題標準答案: (B) 印出 5 4 3 2 1 0 後形成無窮迴圈,因為 i 遞減到 0 以下會環繞成 255,永遠 >= 0

🔍 四個選項逐項深度剖析

選項 A 錯誤解析
此答案忽略了 i 被宣告為 unsigned char,數值範圍只能是0~255,永遠不可能是負數。當 i=0 時執行 i--,並不會變成-1,而是「環繞(wrap around)」變成255(unsigned char 能表示的最大值),所以 i>=0 這個條件永遠是真,迴圈並不會在印出0之後正常結束,“done”永遠不會被印出來。
正確答案完整推導(★ 本題標準答案)
unsigned 型態的變數沒有負數,遞減到0以下時會整數溢位、環繞成該型態能表示的最大值(unsigned char是255),導致 i>=0 恆為真,形成無窮迴圈,會不斷印出255、254、253……一路循環下去,“done”永遠不會被印出來,選 (B)。
選項 C 錯誤解析
把 unsigned 宣告用在迴圈計數器完全合法,可以正常通過編譯,這不是語法錯誤,而是一個能順利通過編譯、卻在執行期造成無窮迴圈的邏輯陷阱——往往比編譯期就能抓到的錯誤更難察覺,也更危險。
選項 D 錯誤解析
此答案忽略了 unsigned 型態溢位環繞的特性,誤以為 i 遞減到0之後、再減1就會像一般有號整數變成-1那樣讓迴圈自然結束,但 unsigned 變數並不會出現負值,這個「安全煞車」在這裡並不存在,迴圈不會自己停下來。

10 考前衝刺 10 秒速記口訣 & 核心知識檢核清單

✅
三種迴圈選用時機
次數已知用 for;先判斷才做用 while;至少要做一次才判斷用 do-while。
✅
for 執行順序
初始化(僅一次)→ 條件判斷 → 執行本體 → 遞增/遞減 → 回到條件判斷。
✅
break 與 continue
break 立刻完全結束整個迴圈;continue 只跳過本次剩下的程式碼,回到條件判斷。
✅
continue 在 while 裡的隱藏陷阱
若遞增變數寫在本體最後一行,continue 會連遞增也一起跳過,導致同一位置被重複處理。
✅
unsigned 溢位口訣
「unsigned 沒有負的家,減到底只會繞回來」——看到 unsigned 計數器搭配遞減與 >=0,立刻提高警覺。
✅
巢狀迴圈追蹤
外層每跑一輪,內層就完整跑一次;累加變數宣告在外層迴圈外就不會被中途重設。
✅
變數遮蔽(shadowing)
函式內重新宣告同名變數會遮蔽外層同名變數,修改外層的那個對函式內完全無效。