for、while 迴圈

May 22, 2022

如果要進行重複性指令執行,可以使用迴圈。

for 迴圈

for 迴圈的基本語法之一如下:

for(初始式; 執行結果必須是boolean的重複式; 重複式) {
    陳述句;
}

for 迴圈語法的圓括號中,初始式只執行一次,通常用來宣告或初始變數,如果是宣告變數,結束 for 迴圈後變數就會消失。第一個分號後則是每次執行迴圈本體前會執行一次,必須是 truefalse 的結果,true 就會執行迴圈本體,false 就會結束迴圈,第二個分號後,則是每次執行完迴圈本體後會執行一次。

實際來看個 for 迴圈範例,在文字模式下從 1 顯示到 10:

package cc.openhome;

public class OneToTen {
    public static void main(String[] args) {
        for(var i = 1; i <= 10; i++) {
            System.out.println(i);
        }
    }
}

這個程式白話讀來,就是從 i 等於 1,只要 i 小於等於 10 就執行迴圈本體,然後遞增 i,這是 for 迴圈的常見的應用方式。

如果 for 本體只有一行陳述句,{} 可以省略,不過為了可讀性與可維護性而言,建議就算只有一行陳述句,也要撰寫 {} 明確定義範圍。

for 迴圈圓括號中第二個複合陳述區塊若沒有撰寫,預設就是 true,偶而看到有人如下撰寫的話,表示無窮迴圈:

for(;;) {
    ...
}

for 中包括一個 if 陳述時:

while 迴圈

while 迴圈可根據指定條件式來判斷是否執行迴圈本體,語法如下所示:

while(條件式) {
    陳述句;
}

如果迴圈本體只有一個陳述句,while{} 可以省略不寫,但為了可讀性,建議還是撰寫。

while 主要用於停止條件必須在執行時期判斷的重複性動作,例如在一個使用者輸入介面,使用者可能輸入的學生名稱個數未知,只知道要結束時會輸入 quit,就可以使用 while 迴圈。

底下是個很無聊的遊戲,看誰可以最久不撞到這個數字5:

package cc.openhome;

public class RandomStop {
    public static void main(String[] args) {
        while(true) {
            var number = (int) (Math.random() * 10);
            System.out.println(number);
            if(number == 5) {
                break;
            }
        }
        System.out.println("I hit 5....Orz");
    }
}

這個範例的 while 判斷式直接設為 true,表示每次 while 重來就直接執行迴圈本體,Math.random 會隨機產生 0.0 到小於 1.0 的值,乘上 10 再裁掉小數部份,表示產生 0 到 9 的數,在 while 迴圈中如果執行到 break,會離開迴圈本體。

while 迴圈有時稱為前測式迴圈,因為會在迴圈執行前就進行條件判斷,如果想先執行一些動作,再判斷要不要重複,則可以使用 do/while,又稱後測式迴圈,do/while 的語法如下所示:

do {
    陳述句;
} while(條件式);

while 後面是以分號 ; 作為結束,這個很常被忽略;可以將上一個範例改為 do/while

package cc.openhome;

public class RandomStop2 {
    public static void main(String[] args) {
        var number = -1;
        do {
            number = (int) (Math.random() * 10);
            System.out.println(number);
        } while(number != 5);
        System.out.println("I hit 5....Orz");
    }
}

break 與 continue

break 可以離開目前 switchforwhiledo/while 的區塊,並執行區塊後下一個陳述句,在 switch 主要用來中斷下個 case 比對,在 forwhiledo/while,主要用於中斷目前迴圈。

continue 作用與 break 類似,不過使用於迴圈,break 會結束區塊執行,而 continue 只會略過之後陳述句,並回到迴圈區塊開頭進行下一次迴圈,而不是離開迴圈。例如:

for(var i = 1; i < 10; i++) {
    if(i == 5) {
        break;
    }
    System.out.printf("i = %d%n", i);
}

這段程式會顯示 i = 1 到 i = 4,因為在 i 等於 5 時就會執行 break 而離開迴圈。再看下面這個程式:

for(var i = 1; i < 10; i++) {
    if(i == 5) {
        continue;
    }
    System.out.printf("i = %d%n", i);
}

這段程式會顯示 i =1 到 4,以及 6 到 9,當 i 等於 5 時,會執行 continue 直接略過之後陳述句,也就是該次的 System.out.printf 該行並沒有被執行,直接從區塊開頭執行下一次迴圈,所以 i = 5 沒有被顯示。

breakcontinue 還可以配合標籤使用,例如本來 break 只會離開 for 迴圈,設定標籤與區塊,可以離開整個區塊。

back : {
    for(var i = 0; i < 10; i++) {
        if(i == 9) {
            System.out.println("break");
            break back;
        }
    }
    System.out.println("test");
}

程式執行結果會顯示 breakback 是個標籤,當 break back 時,返回至 back 標籤處,之後整個 back 區塊不執行而跳過,所以 System.out.println("test") 該行不會執行。

continue 也有類似的用法,只不過標籤只能設定在 for 之前。例如:

back1:
for(int i = 0; i < 10; i++){
    back2:
    for(int j = 0; j < 10; j++) {
        if(j == 9) {
            continue back1;
        }
    }
    System.out.println("test");
}

continue 配合標籤,可以自由地跳至任何一層 for 迴圈,可以試試 continue back1continue back2 的不同,設定 back1 時,System.out.println("test") 不會執行。

分享到 LinkedIn 分享到 Facebook 分享到 Twitter