3.5 if / else if / else
現在我們有了條件判斷的工具(比較和邏輯運算子),我們需要根據這些條件分支執行不同的程式碼。if 語句就是用來做這件事的。
if 小括號裡放的是一個「條件」,這個條件最後會被看成 true 或 false(還記得 3.2、3.3 嗎?比較和邏輯運算的結果就是布林值):true 就執行大括號裡的程式,false 就跳過。像 score >= 60、x > 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";
}
¶範例程式碼:把流程圖變成程式
還記得單元開頭〈想像一下…〉的那張成績判斷流程圖嗎?現在我們已經備齊所有工具,可以把它翻成程式了。先把圖再看一次:
流程圖「從上往下、每個菱形做一次判斷」的結構,正好對應 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 走一遍:
- 先檢查
score >= 60?→55 >= 60是false,跳過。 - 再檢查
score >= 50?→55 >= 50是true→ 印出Make-up Exam,整組if到此結束。 - 後面的
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 個數 M 是 2,5,8,得到 200 元。
- 若兩個數字相同,得到 50 元。
重點是:這題的獎金可以累加。例如輸入 5 5 時,N 是奇數,且 M 是 5,兩個數字也相同,所以三個獎都中,答案是 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 實現。