For 迴圈

極為常見

還記得前面提到的 while 迴圈嗎?for 迴圈也是一種迴圈,但是比 while 迴圈更為簡潔。for 迴圈通常用於迭代一個固定次數的迴圈,而 while 迴圈則是比較適合用於迭代一個不確定次數的迴圈。

語法

在熟悉了 while 迴圈之後,如果你想要寫一段程式來重複執行某個區塊 5 次,你應該會寫出下面這段程式碼:

int i = 1;

while (i <= 5) {
    cout << i << ' ';
    i++;
}

這段程式碼會印出 1 2 3 4 5,但是如果你使用 for 迴圈,你可以更為簡潔地達到相同的效果:

for (int i = 1; i <= 5; i++) {
    cout << i << ' ';
}

可以看到,for 迴圈的括號中包含了三個部分,分別用兩個分號隔開。第一個部分是執行你進這個迴圈第一件要做的事 ( 絕大多數情況是設定變數的初始值,然而有的時候會空著或放別的東西 ),第二個是設定迴圈終止條件,第三個區塊則是可以在每一次迴圈執行完畢後要做的事 ( 通常是調整變數的值 ),而包在大括號裡的則是每層迴圈要做的事。所以執行的順序是 初始化 -> 檢查迴圈終止條件 ( 回傳的布林值是 0 就 break ) -> 執行大括號區塊 -> 執行第三個區塊 -> 檢查迴圈終止條件...。流程圖如下:

alt text

事實上,for 迴圈的執行概念與 while 迴圈是非常相似的,只是將初始化、迴圈終止條件等等都放在了一個地方,以上面印出 1 2 3 4 5 的程式為例:

(初始化)

while (終止條件) {
    // 程式碼
    (更新變數的值)
}

轉換成 for 迴圈的語法結構:

for (初始化; 終止條件; 更新變數的值) {
    // 程式碼
}

相信看到這裡,你應該已經能夠理解 for 迴圈的基本語法了!接下來的章節將會介紹更多關於迴圈的用法,讓你更加熟悉各種應用。

不完整的 for 迴圈

前面我們提到了 for 迴圈大概可以分成三個部分:初始化、迴圈終止條件、更新變數的值。然而這三個部分其實都不是必須的,有時候你可能會需要省略其中一部分或兩部分,甚至是全部都省略。

比如說,如果你想把 for 迴圈當作一個無限迴圈來使用,你可以省略所有參數:

for (;;) {
    // 無限迴圈
}

或者是其實你的初始化已經在更前面執行了,你可以省略初始化部分:

int i = 1;

for (; i <= 5; i++) {
    cout << i << ' ';
}

或者是你的迴圈終止條件已經在迴圈內部判斷了,你可以省略迴圈終止條件:

int i = 1;

for (; ; i++) {
    if (i > 5) {
        break;
    }
    cout << i << ' ';
}

這些都是合法的 for 迴圈寫法,你可以根據自己的需求來選擇是否省略某些部分。

巢狀迴圈

巢狀迴圈,顧名思義是由兩個 ( 甚至是更多個 ) 的迴圈疊在一起產生的。以下是一個嵌套兩層的 for 迴圈:

for (int i = 2; i < 10; i++) {
    for (int j = 1; j < 10; j++) {
        cout << i << "*" << j << " ";
    }
    cout << endl;
}

這是一個九九乘法的程式碼,他是一個典型的巢狀迴圈實作。下方是程式碼的輸出結果,我們透過外層的 i 迴圈來控制被乘數的增加,而透過內層的 j 迴圈來控制乘數的增加。根據結果我們可以發現,外層的 i 迴圈每增加一圈裡面的 j 迴圈都會再次從 1 執行到 9

2*1 2*2 2*3 2*4 2*5 2*6 2*7 2*8 2*9
3*1 3*2 3*3 3*4 3*5 3*6 3*7 3*8 3*9
4*1 4*2 4*3 4*4 4*5 4*6 4*7 4*8 4*9
5*1 5*2 5*3 5*4 5*5 5*6 5*7 5*8 5*9
6*1 6*2 6*3 6*4 6*5 6*6 6*7 6*8 6*9
7*1 7*2 7*3 7*4 7*5 7*6 7*7 7*8 7*9
8*1 8*2 8*3 8*4 8*5 8*6 8*7 8*8 8*9
9*1 9*2 9*3 9*4 9*5 9*6 9*7 9*8 9*9

小測驗

以下哪個程式碼片段會導致無窮迴圈?