4.3 for 迴圈

for 迴圈特別適合有明確計數器的場景——你要跑固定圈數,或掃過一段範圍(例如 1 到 n)。它把「初始化、條件判斷、每次迴圈後的更新」都收在同一行,讓程式碼更緊湊,也不容易漏掉其中某一段。

for 迴圈的結構:

for (初始化; 條件式; 更新運算式) {
    程式碼區塊
}

三個部分的意義:

  1. 初始化:迴圈開始前執行一次,通常宣告計數器
  2. 條件式:每次迴圈開始前都檢查,為 false 時停止
  3. 更新運算式:每次迴圈結束後執行,通常是計數器加 1

執行流程:

  1. 執行初始化(只一次)
  2. 檢查條件式
  3. 如果為 true,執行程式碼區塊,然後執行更新運算式,回到步驟 2
  4. 如果為 false,跳出迴圈
圖 4-2:for 迴圈執行流程

4.2while 相比,for 多了藍色的兩塊:初始化在進迴圈前只做一次,更新運算式在每一圈結束後才執行——這正是 for 把「初始化、條件、更新」收在一行的原因。

範例程式碼

範例 1:印出 1 到 10(和 4.2 的 while 對照)

4.2 我們用 while 印出 1 到 10,計數器的「初始化、條件、更新」散在三個地方。改用 for,這三件事收進同一行:

#include<iostream>
using namespace std;
int main() {
    // 初始化 i = 1;條件 i <= 10;每圈結束後 i++
    for (int i = 1; i <= 10; i++) {
        cout << i << "\n";
    }

    return 0;
}

執行結果:

1
2
3
...(中間略)
10

對照 4.2while 版本,forint i = 1;i <= 10i += 1 三段從三行收進括號裡,一眼就看出「這個迴圈讓 i 從 1 數到 10」。

for 的三段什麼時候跑? for 最容易搞混的是「三段各在什麼時機執行」。用範例 1 追蹤,重點看三段的觸發順序:

步驟 動作 i
進迴圈 初始化 int i = 1只做這一次 1
第 1 圈 檢查 i <= 10?成立 → 印出 1 → 更新 i++ 1 → 2
第 2 圈 檢查 2 <= 10?成立 → 印出 2 → 更新 i++ 2 → 3
第 10 圈 檢查 10 <= 10?成立 → 印出 10 → 更新 i++ 10 → 11
結束 檢查 11 <= 10不成立 → 跳出 11

順序是:初始化一次 → (檢查 → 執行 → 更新)一直循環 → 檢查失敗才停。注意更新 i++ 是在印完之後才發生,所以最後一次真的印出的是 10、不是 11。

範例 2:印出一個數的所有因數

給一個正整數 n,印出它的所有因數(能整除 n 的數)。

因數一定落在 1 到 n 之間,所以讓計數器 i 掃過整個範圍 1 到 n,逐一檢查「i 能不能整除 n」——這種「掃過一段固定範圍」正是 for 最自然的場景。

#include<iostream>
using namespace std;
int main() {
    int n;
    cin >> n;

    for (int i = 1; i <= n; i++) {   // 掃過 1 到 n 每一個數
        if (n % i == 0) {            // i 能整除 n → i 是因數
            cout << i << " ";
        }
    }
    cout << "\n";

    return 0;
}

執行結果:(假設輸入為 12

1 2 3 4 6 12

i 從 1 一路走到 12,每一格都問一次「12 % i 是不是 0」,是就印出來。這裡的 i 同時扮演「掃到哪」和「要檢查的因數」,一個計數器兩用。

大括號可以省略嗎?

規則和 3.5 的 if 一模一樣:迴圈體只有「一個陳述式」時,可以省略大括號

for (int i = 1; i <= n; i++)
    cout << i << "\n";      // 迴圈體只有一句,可以省略 { }

但省略的陷阱也一樣:之後想在迴圈裡加第二句時,如果忘了補回大括號,第二句其實在迴圈外:

for (int i = 1; i <= n; i++)
    cout << i << "\n";
    sum += i;               // ✗ 縮排看起來在迴圈裡,其實只執行一次!

變數宣告在迴圈內還是迴圈外?

宣告在迴圈大括號裡面的變數,每一圈都會重新誕生、重新初始化(複習 3.8 變數範圍的生命週期):

for (int i = 1; i <= n; i++) {
    long long sum = 0;   // ✗ 每一圈都被重設成 0
    int x;
    cin >> x;
    sum += x;            // 永遠只加到當圈讀入的 x
}
  • 只在當圈使用的變數(例如每圈讀入的 x)→ 宣告在迴圈內,乾淨俐落。
  • 跨圈記住東西的變數(累加總和、目前最小值、答案)→ 一定宣告在迴圈,否則每圈歸零。

迴圈的排版

延續 1.53.5 的排版習慣,whilefor 迴圈也要排得層次分明。重點一樣是縮排大括號的位置;另外 for 的括號裡有三段,也有一套好讀的寫法:

// ✓ 好的排版
for (int i = 0; i < n; i++) {
    sum += i;
}

// ✗ 不好的排版:擠成一團、沒縮排
for(int i=0;i<n;i++){sum+=i;}
規則 ✓ 好的做法 ✗ 不好的做法 為什麼
關鍵字後空一格 for (...)while (...) for(...)while(...) forwhile 是關鍵字,和 ( 空一格,跟函式呼叫區別開
左大括號接行尾 for (...) { { 另起一行 { 放在同一行行尾,省一行、更緊湊
迴圈體縮排一層 { } 裡的語句往右縮 2~4 格 頂著最左邊寫 一眼看出「這些是迴圈裡重複做的事」
三段分號後空格 for (int i = 0; i < n; i++) for (int i=0;i<n;i++) 初始化/條件/更新三段用 ; 隔開更清楚

動手試試看

  1. (暖身)for 計算 1 + 2 + 3 + \dots + 100 並輸出。
  2. (範圍掃描) 讀入正整數 n,把 1 到 n 之間所有的偶數印出來。
  3. (累乘) 讀入正整數 n,計算 1 \times 2 \times \dots \times n(也就是 n 階乘)。想一想:累乘用的變數初始值該設 0 還是 1?為什麼?(提示:n 稍微大一點就會溢位,要用 long long,複習 2.9。)