1 流程圖判斷框對應 if 還是 while:關鍵在「要不要反覆判斷」
把流程圖轉換成程式碼時,最關鍵的第一步是分辨流程圖中的判斷框應該對應到 if(只做一次判斷)還是 while(反覆判斷、形成迴圈)。
| 流程圖描述 | 該用哪個結構 | 原因 |
|---|---|---|
| 「是」則做完一件事就繼續往下走(不再檢查) | if | 只需要判斷一次 |
| 「是」則做完一件事、箭頭繞回來再檢查一次 | while | 需要反覆判斷,直到條件不成立才離開 |
如果流程圖裡「是」的分支執行完動作後,箭頭又繞回同一個判斷框重新檢查,這就是迴圈的特徵,必須用 while(或 for、do-while)——用 if 只會執行一次,不會自動再檢查第二次,不符合流程圖的設計。
2 判斷框的「是/否」方向與迴圈條件的真假邏輯
確定要用 while 之後,還要看清楚流程圖箭頭「是」與「否」各自指向的方向,才能決定迴圈條件該寫成什麼樣的真假邏輯——迴圈要持續執行的條件,正是流程圖裡「是」這條分支所對應的那個判斷本身。
// 流程圖:字數 >= 陣列長度? 是 → 重新詢問並繼續判斷;否 → 往下走
while (StringLength >= ArrayLength) {
printf("請輸入字數: ");
scanf("%d", &StringLength);
}
// 迴圈持續的條件,就是流程圖「是」那條分支對應的判斷本身
流程圖畫的通常是「什麼情況下要重複」(也就是「是」那條分支),但有些人會不小心把「跳出迴圈的條件」(也就是「否」那條分支)直接拿來當迴圈的判斷式,導致整個邏輯顛倒。務必先確認:迴圈的判斷式,寫的應該是「要繼續執行」的條件,不是「要停止」的條件。
3 前置/後置遞減在陣列索引中的差異:倒序輸出的關鍵
用陣列索引搭配前置/後置遞減來實作「倒序輸出」是常見手法:前置遞減 arr[--i] 會先減再當索引使用,後置遞減 arr[i--] 則是先當索引使用再減,兩者存資料的位置會差一格。
int i = 3;
char buf[4] = {0};
buf[--i] = 'C'; // 前置:i先變2,再存 → buf[2]='C'
buf[--i] = 'B'; // i變1 → buf[1]='B'
buf[--i] = 'A'; // i變0 → buf[0]='A'
printf("%s", buf); // 輸出 "ABC"(存入順序C,B,A,位置卻是0,1,2 → 讀出剛好是輸入的反序)
如果誤用後置遞減 arr[i--],第一次會先用 i「目前」的值當索引存入,才把 i 減1——這代表如果 i 從陣列的最大有效索引開始遞減,索引0 永遠不會被存到任何值,仍是宣告時自動補0而成的 '\0'。用 %s 從索引0開始讀取字串時,一遇到 '\0' 就立刻停止,結果會印出空字串,而不是預期的內容。
4 用「結束信號」(sentinel)控制迴圈:流程圖常見手法
很多流程圖用一個特殊值(sentinel,結束信號)代表「資料輸入完畢」,程式只要不斷判斷是否讀到這個值,就能把流程圖的迴圈邏輯直接轉成 while。
#include <stdio.h>
int main(void) {
int data[] = {4, 8, 15, 16, 23, -1}; // -1是流程圖中約定的「結束信號」
int i = 0, sum = 0;
while (data[i] != -1) { // 流程圖的判斷框:是否為結束信號?
sum += data[i];
i++;
}
printf("總和 = %d\n", sum); // 66
return 0;
}
結束信號必須選一個「絕對不會是正常資料」的值(例如成績資料用-1、身分證字號輸入用空字串),這樣程式才能明確分辨「這是正常資料」還是「該停止了」,不會誤判。
6 常考陷阱總複習:流程圖轉程式碼的檢查清單
把流程圖轉成程式碼後,建議依下面的清單逐一核對,確保程式碼真正忠實地呈現了流程圖的設計:
| □ | 檢查項目 |
|---|---|
| 1 | 判斷框如果箭頭會繞回來重新檢查,是不是正確用了迴圈(while/for/do-while),而不是只判斷一次的if? |
| 2 | 迴圈條件寫的是「要繼續執行」的條件,而不是「要停止」的條件(兩者互為反向)? |
| 3 | 陣列索引用前置或後置遞增/遞減時,有沒有搞清楚「先變動再存取」還是「先存取再變動」? |
| 4 | 若流程圖用sentinel值代表結束,選的值是否確定不會跟正常資料混淆? |
| 5 | 流程圖要求「至少執行一次」的迴圈(如選單),是否正確使用了do-while? |
7 111~115 歷屆統測真題全選項深度剖析(共 2 題)
以下收錄統測專業科目(二)近年全部 2 題流程圖轉程式碼真題。每題均提供高解析度原始考題掃描圖、互動選項按鈕與所有選項逐項深入解析:
const int ArrayLength = 10;
char StringIn[ArrayLength] = { 0 };
int StringLength = 10;
if(StringLength <= ArrayLength)
{
std::cout << "請輸入字數: ";
std::cin >> StringLength;
}
while (StringLength > 0)
{
std::cout << "請輸入英數文字: ";
std::cin >> StringIn[StringLength--];
}
std::cout << StringIn;
🔍 四個選項逐項深度剖析
if 只會執行一次判斷,不管條件成立與否都不會自動再檢查一次,不符合流程圖「是則重複詢問再回到判斷」的要求;而且 <(小於)判斷的方向,也跟流程圖描述的「字數是否大於等於陣列長度」條件方向不符。if 只執行一次判斷,不符合流程圖要求的重複迴圈結構;!=(不等於)這個判斷條件,也沒有正確表達「大於等於陣列長度」這個需求。while(StringLength>=ArrayLength),選 (C)。while 迴圈結構,但判斷條件 !=(不等於)並沒有正確表達流程圖裡「大於等於陣列長度」這個要重複執行的條件——用 != 會讓迴圈在字數「等於」陣列長度時就跳出,但流程圖要求的是「大於等於」都要繼續詢問,只有小於陣列長度才停止。🔍 四個選項逐項深度剖析
StringIn[StringLength--] 這種後置遞減的索引寫法)完全無關,不能解決題目要求的倒序輸出問題。StringLength<0 這個條件方向本身也不合理(StringLength從正整數開始遞減,理應是判斷是否還大於0才要繼續輸入,不是判斷是否小於0),跟解決倒序輸出的根本問題無關。StringIn[StringLength--](後置遞減),第一次輸入用StringLength的「原始值」(例如6)當索引存入,之後才遞減,導致字元被依序存到索引6、5、4、3、2、1,索引0仍是初始值 '\0',cout 輸出字串時因為索引0剛好是字串結尾符號,反而會印出空字串。改為前置遞減 StringIn[--StringLength]:先遞減、再拿遞減後的新值當索引,第1個輸入的字元會存入索引5,……第6個(最後輸入的字元)存入索引0,cout 從索引0開始讀取字串時,會先讀到「最後輸入的字元」,依序往後讀到「最先輸入的字元」,恰好呈現輸入順序的倒序字串,選 (C)。StringIn[StringLength++](後置遞增)會讓索引不斷往「更大」的方向移動,而不是往回縮到0,不僅方向錯誤,還很可能讓索引超出 StringIn 陣列宣告的有效範圍(陣列大小是ArrayLength=10),導致存取越界的記憶體,無法達到倒序輸出的效果。8 高職段考與模擬精選實戰題(5 題全選項解析)
透過以下 5 題精選模擬試題,全面檢驗你對if/while選擇、前置/後置遞減、sentinel與do-while選單流程的掌握度:
int passengers = 2, maxCapacity = 8;
/* 行號X */ (passengers < maxCapacity) {
printf("讓乘客進入,目前人數%d\n", ++passengers);
}
printf("關門出發,最終人數%d", passengers);
🔍 四個選項逐項深度剖析
while 會不斷檢查條件,只要 passengers<maxCapacity 還成立就持續執行本體讓乘客進入,直到人數達到上限、條件不成立才跳出迴圈往下執行關門,完全符合流程圖描述的行為,選 (A)。if 只會執行一次判斷,不管條件成立與否都不會自動再次檢查,只能讓「一位」乘客進入,無法達成「持續讓乘客進入直到達到上限」這種需要反覆判斷的迴圈效果。if 與 while 的行為完全不同——if 只執行一次判斷,while 會反覆判斷直到條件不成立為止,兩者在本題這種「需要重複執行直到滿足某個結束條件」的情境下,效果差異非常大,並不是「兩者皆可、效果相同」。do-while 會先執行一次本體,之後才判斷條件,跟流程圖描述的「先判斷條件,是才執行」的順序不完全對應;用 while 更能精確對應流程圖判斷框在動作之前的設計。int idx = 3;
char result[4] = {0};
result[idx--] = 'X'; // 後置遞減:先用3當索引存入,再遞減
result[idx--] = 'Y'; // idx變2,存入索引2,再遞減
result[idx--] = 'Z'; // idx變1,存入索引1,再遞減
printf("%s", result);
🔍 四個選項逐項深度剖析
result[idx--] 是後置遞減:先用idx「目前」的值當索引存入,才把idx減1。所以第1次用idx=3存入'X'(result[3]='X'),idx變2;第2次存入result[2]='Y',idx變1;第3次存入result[1]='Z',idx變0。索引0從頭到尾都沒有被賦值,維持陣列宣告時自動補0而成的 '\0'。printf("%s", result) 從索引0開始讀取,一遇到 '\0' 就立刻停止,所以什麼字元都印不出來,是空字串,選 (A)。%s 是從陣列「索引0」開始讀取,不是照存入的時間順序讀取,而索引0這個位置從頭到尾都沒有被寫入任何字元,所以不會印出XYZ這樣的內容。--idx)才會有的效果,本題用的是後置遞減(idx--),索引0並沒有被存到任何字元,不會呈現ZYX這樣的倒序結果。int idx = 3;
char result[4] = {0};
result[--idx] = 'X'; // 前置遞減:先遞減再當索引使用
result[--idx] = 'Y';
result[--idx] = 'Z';
printf("%s", result);
🔍 四個選項逐項深度剖析
result[--idx] 是前置遞減:先把idx減1,才用「減完之後」的新值當索引存入。第1次:idx從3減為2,存入result[2]='X';第2次:idx從2減為1,存入result[1]='Y';第3次:idx從1減為0,存入result[0]='Z'。索引0這次確實被賦值為'Z',printf("%s", result) 從索引0開始讀取:Z、Y、X,讀到索引3(未賦值、自動補0的 '\0')就停止,印出"ZYX"——正好是輸入順序('X','Y','Z')的反序,選 (A)。%s 讀取的是陣列「索引由小到大」的內容,不是程式執行的時間順序;本題前置遞減讓索引由大到小依序被填入,索引0填入的其實是最後賦值的'Z',不是最先賦值的'X'。idx--)才會出現的「索引0未被賦值、印出空字串」的結果(見上一題),本題用的是前置遞減(--idx),索引0確實會被賦值到,不會是空字串。int scores[] = {85, 92, 78, -1};
int i = 0, total = 0, count = 0;
while (scores[i] != -1) {
total += scores[i];
count++;
i++;
}
printf("平均分數=%.1f", (float)total/count);
🔍 四個選項逐項深度剖析
(float)255/3=85.0,選 (A)。scores[i]!=-1 會在讀到-1時變成假,正常跳出迴圈,不會無窮迴圈下去。int actions[3] = {2, 5, 0};
int i = 0, sum = 0;
do {
int a = actions[i++];
if (a == 0) break;
sum += a;
} while (1);
printf("%d", sum);
🔍 四個選項逐項深度剖析
while(1)(條件恆為真)與內部的break,是流程圖中「選單式」迴圈的典型寫法:先執行一次本體讀取下一個動作,若讀到結束信號0就用break跳出迴圈,否則把值累加進sum、繼續下一輪。逐輪追蹤:第1輪a=2(非0),sum=2;第2輪a=5(非0),sum=7;第3輪a=0,觸發break,立刻跳出迴圈,不執行 sum+=a 這一行。最終sum=7,選 (A)。while(1) 的條件恆為真,迴圈會持續執行,直到讀到結束信號0觸發break才會真正停止,中途至少會讀取到actions[1]=5並累加進sum。while(1)(條件恆為真、看似會無窮迴圈),但迴圈內部有明確的break敘述,會在讀到結束信號值0(也就是actions陣列中約定的「結束標記」)時被觸發,讓迴圈確實終止,不會無窮迴圈下去。9 考前衝刺 10 秒速記口訣 & 核心知識檢核清單
箭頭會繞回來重新檢查=迴圈(while),只判斷一次就往下走=if。
迴圈判斷式對應流程圖「是」那條要重複執行的分支,不是「否」跳出的分支。
arr[--i]先減再存(倒序正確);arr[i--]先存再減(索引0永遠填不到)。
要選一個絕對不會是正常資料的值,讓while迴圈能明確判斷是否該停止讀取。
至少要執行一次才能判斷是否重複的情境(如選單),用do-while最貼切。