3.5 if / else if / else

現在我們有了條件判斷的工具(比較和邏輯運算子),我們需要根據這些條件分支執行不同的程式碼if 語句就是用來做這件事的。

if 小括號裡放的是一個「條件」,這個條件最後會被看成 truefalse(還記得 3.23.3 嗎?比較和邏輯運算的結果就是布林值):true 就執行大括號裡的程式,false 就跳過。像 score >= 60x > 0 && x < 10 這種都可以直接放進去。

基本 if 語句

if (條件) {
    // 條件為 true 時執行
}

if/else 語句

if (條件) {
    // 條件為 true 時執行
} else {
    // 條件為 false 時執行
}

if/else if/else 語句

if (條件1) {
    // 條件1為 true 時執行
} else if (條件2) {
    // 條件1為 false,條件2為 true 時執行
} else if (條件3) {
    // 條件1、2 為 false,條件3為 true 時執行
} else {
    // 以上條件都為 false 時執行
}

if / else 的排版

延續 1.5 學過的排版習慣,if / else 也有一套大家公認好讀的寫法,重點在縮排大括號的位置

// ✓ 好的排版:層次分明
if (score >= 60) {
    cout << "Passed";
} else {
    cout << "Failed";
}

// ✗ 不好的排版:擠成一團、沒縮排,看不出結構
if(score>=60){cout<<"Passed";}else{cout<<"Failed";}
規則 ✓ 好的做法 ✗ 不好的做法 為什麼
if 後空一格 if (x > 5) if(x>5) if 是關鍵字,和 ( 空一格,跟 main() 這種「名字緊接括號」的寫法區別開
左大括號接行尾 if (x > 5) { { 另起一行 { 放在條件同一行行尾,省一行、更緊湊
內容縮排一層 { } 裡的語句往右縮 2~4 格 頂著最左邊寫 一眼看出「這些是 if 成立時要做的事」
else 貼著 } } else { else 另起一行 else 跟右大括號同一行,讀起來連貫

(條件裡的運算子一樣要在周圍加空格,例如寫 score >= 60 而不是 score>=60——這點 1.5 已經講過。)

大括號可以省略嗎?

if(或 else)底下只有一行要執行時,大括號 { } 其實可以省略:

// 這兩種寫法完全一樣
if (score >= 60)
    cout << "Passed";

if (score >= 60) {
    cout << "Passed";
}

但這裡藏著一個新手最常踩的坑:省略大括號時,if 只管緊接著的「那一行」。如果條件成立時你想做兩件以上的事,就一定要用大括號把它們框起來,否則只有第一行受 if 控制:

// ✗ 錯誤:以為兩行都屬於 if
if (score >= 60)
    cout << "Passed\n";
    cout << "恭喜你!\n";   // 這行其實「永遠」會印,跟 if 完全無關!

// ✓ 正確:多行一定要用大括號框起來
if (score >= 60) {
    cout << "Passed\n";
    cout << "恭喜你!\n";
}

範例程式碼:把流程圖變成程式

還記得單元開頭〈想像一下…〉的那張成績判斷流程圖嗎?現在我們已經備齊所有工具,可以把它翻成程式了。先把圖再看一次:

圖 3-1:成績判斷流程圖

流程圖「從上往下、每個菱形做一次判斷」的結構,正好對應 if / else if / else:第一個菱形 score >= 60 就是 if,第二個菱形 score >= 50 就是 else if,兩個都不成立時的最後一條路就是 else

#include <iostream>
using namespace std;

int main() {
    int score;
    cin >> score;  // 讀入分數

    if (score >= 60) {                    // 第一個菱形:score >= 60?
        cout << "Passed" << endl;         // 成立 → 通過
    } else if (score >= 50) {             // 第二個菱形:score >= 50?
        cout << "Make-up Exam" << endl;   // 成立 → 補考
    } else {                              // 兩個菱形都不成立
        cout << "Retake Course" << endl;  // → 重修
    }

    return 0;
}

執行結果(輸入 55)

Make-up Exam

else if 是「由上往下、第一個成立就停」

if / else if / else 的執行方式是:從上到下逐一檢查,遇到第一個成立的條件就執行它、然後整組結束,後面的都不再看。拿輸入 55 走一遍:

  1. 先檢查 score >= 60?→ 55 >= 60false,跳過。
  2. 再檢查 score >= 50?→ 55 >= 50true → 印出 Make-up Exam整組 if 到此結束
  3. 後面的 else 不再檢查。

邏輯等效性

有時候,同一個邏輯可以用不同的方式寫。例如:

// 方式1:if/else if(推薦)
if (score >= 90) {
    cout << "A";
} else if (score >= 80) {
    cout << "B";
} else if (score >= 70) {
    cout << "C";
}

// 方式2:單獨的 if(較差)
if (score >= 90) {
    cout << "A";
}
if (score >= 80 && score < 90) {  // 注意:要加額外的上界條件
    cout << "B";
}
if (score >= 70 && score < 80) {
    cout << "C";
}

方式1 更清潔且避免錯誤,因為 else if 自動確保只有一個分支會執行。

彼此獨立的條件:多個 if 累加

反過來,有些題目的條件彼此獨立——每個條件各自成立就各自貢獻一筆,互不影響。這時不要硬塞進一組 else if,改用多個獨立的 if,搭配「先用變數存答案、最後再輸出」。

直接看後面的練習題 刮刮樂兌獎 2(scredeem2)。題目給你兩個 0 \sim 9 的數字 N, M,三種獎項如下:

  • 若第 1 個數 N 是奇數,得到 100 元。
  • 若第 2 個數 M2,5,8,得到 200 元。
  • 若兩個數字相同,得到 50 元。

重點是:這題的獎金可以累加。例如輸入 5 5 時,N 是奇數,且 M5,兩個數字也相同,所以三個獎都中,答案是 100+200+50=350

如果硬把它寫成 if / else if / else,就會變成列舉「三個獎項中哪些有中」的所有情況。三個條件各自有成立/不成立兩種狀態,所以一共有 2^3=8 種組合:

int n, m;
cin >> n >> m;

bool oddFirst = (n % 2 == 1);
bool specialSecond = (m == 2 || m == 5 || m == 8);
bool same = (n == m);

if (oddFirst && specialSecond && same) {
    cout << 350 << endl;
} else if (oddFirst && specialSecond && !same) {
    cout << 300 << endl;
} else if (oddFirst && !specialSecond && same) {
    cout << 150 << endl;
} else if (oddFirst && !specialSecond && !same) {
    cout << 100 << endl;
} else if (!oddFirst && specialSecond && same) {
    cout << 250 << endl;
} else if (!oddFirst && specialSecond && !same) {
    cout << 200 << endl;
} else if (!oddFirst && !specialSecond && same) {
    cout << 50 << endl;
} else {
    cout << 0 << endl;
}

這份程式不是不能算,但為了輸出 8 種可能答案,寫了 8{ ... } 區塊;條件又長,很容易漏掉某一種組合,或把某個金額加錯。

更簡單的想法是:這三個條件彼此不會互相排除,所以每個條件各自檢查一次,成立就把獎金加進答案:

int n, m;
cin >> n >> m;

int ans = 0;
if (n % 2 == 1) {
    ans += 100;
}
if (m == 2 || m == 5 || m == 8) {
    ans += 200;
}
if (n == m) {
    ans += 50;
}

cout << ans << endl;

每個 if 都會被檢查一次,只要條件成立,就把對應獎金加進 ans。所以同時符合多個條件時,獎金自然會一筆一筆累加。

若誤寫成 if / else if,程式遇到第一個成立的條件就會停下來,同時符合兩個以上獎項時也只會加到第一筆獎金——意思完全不同。判斷準則:

  • 各條件對答案的影響獨立(可同時成立、效果疊加)→ 多個 if 累加
  • 分支互斥(只能走一條路)→ if / else if / else

短路求值的實用時機

還記得 3.3 提過的短路求值嗎?&& 左邊如果是 false,右邊就完全不會被計算。這個特性可以幫我們在條件裡先做安全檢查,避免程式當掉。

想像你要算一位同學的平均分數:把總分 total 除以考試科目數 count。但萬一他還沒考任何一科(count 是 0),total / count 就變成「除以 0」——這在數學裡沒有意義,程式真的算下去會直接當掉

我們可以把「科目數不是 0」放在 && 的左邊當守門員

int total, count;   // total:總分,count:考了幾科
cin >> total >> count;

// 還沒考任何一科時 count 是 0。
// && 左邊 (count != 0) 為 false,右邊的 total / count 就不會被計算,
// 因此不會發生「除以 0」把程式弄當掉。
if (count != 0 && total / count >= 60) {
    cout << "平均及格!" << endl;
}

順序很重要:如果反過來寫成 if (total / count >= 60 && count != 0),當 count 是 0 時,左邊的 total / count被計算 → 立刻當掉,右邊那位守門員根本來不及擋。所以要把「保護用」的條件放在前面,讓它先攔下來。

動手試試看

寫一個程式,輸入一個月份數字(1-12),輸出該月有多少天(假設非閏年)。用 if/else if/else 實現。