迭代控制結構 (Iteration Control Structures)

    前言

    迭代 (iteration) 或是迴圈 (loop) 用於重覆執行一段程式碼,這樣就不用重覆撰寫該段程式碼,日後要修改時也要只改一個地方即可。本文介紹 Perl 的迴圈語法。

    while 敘述

    while 用於執行次數未定的迴圈,其虛擬碼如下:

    while (condition) {
        # Do something.
    }
    

    condition 條件成立的前提下,會反覆執行 something 區塊內的程式碼,直到不符合 condition 條件時,才結束 while 迴圈。

    以下是實例:

    my $n = 10;
    
    while ($n > 0) {
        print "Count down $n\n";
        
        $n--;
    }
    

    也可以用 continue 改寫如下:

    my $n = 10;
    
    while ($n > 0) {
        print "Count down $n\n";
    } continue {    
        $n--;
    }
    

    這種寫法的好處是可將計數器的部分和其他程式碼分開,易於閱讀。

    以下 while 迴圈為無窮迴圈:

    while (1) {
        # Do something.
    }
    

    如果我們不中斷這個迴圈,這個迴圈會不斷地進行下去;有時候無窮迴圈是刻意寫的,有時候則是程式寫錯引發的臭蟲 (bug)。我們會在後文介紹一些改變迴圈進行的方法。

    until 敘述

    untilwhile 用法相同但語意相反。由於 until 本身隱含著否定的意味,在複合條件句上會比較難寫,除非某段程式碼在語意上剛好符合,用 while 改寫比較會比較好閱讀。以下是 until 的實例:

    my $n = 10;
    
    until ($n <= 0) {
        print "Count down $n\n";
        
        $n--;
    }
    

    同樣地,也可以用 continue 改寫如下:

    my $n = 10;
    
    until ($n <= 0) {
        print "Count down $n\n";
    } continue {    
        $n--;
    }
    

    for 敘述

    在 Perl 之中,for 有兩種用法,一種是搭配計數器 (counter),一種是搭配串列 (list)。

    使用計數器的 for

    這種用法源自於 C 家族語言。實例如下:

    for (my $i = 1; $i <= 10; $i++) {
        print "\$i is $i\n";
    }
    

    其實 for 迴圈可以改寫成等效的 while 迴圈。沿續先前的例子:

    {
        my $i = 1;
        
        while ($i <= 10) {
            print "\$i is $i\n";
        } continue {
            $i++;
        }
    }
    

    我們用額外的區塊是為了避免出現新的變數,汙染命名空間。

    for (;;)while(1) 同義,皆是無窮迴圈:

    for (;;) {
        # Do something here.
    }
    

    使用串列的 for

    我們留到介紹陣列及串列時一併講解。

    foreach

    foreachfor 是同義字,可交互使用。有些 Perl 程式人會用 for 搭配計數器而 foreach 搭配串列,這只是撰碼風格,不是硬性規定。

    改變迴圈執行順序

    next 敘述

    next 用於略過當次的迭代,繼續下一輪的迴圈,通常會和 if 搭配使用。如下例:

    for (my $n = 10; $n > 0; $n--) {
        next if $n % 2 != 0;
        
        print "Count down $n\n";
    }
    

    redo 敘述

    redo 用於重新開始同一次迭代。如下例:

    my $n;
    
    while (1) {
        $n = int(rand(10)) + 1;
        $n % 2 == 0 or redo;
        last;
    }
    
    print $n, "\n";
    

    在這個程式中,當 $n 不為偶數時就重新取一個介於 1 至 10 的隨機整數,直到 $n 為偶數時才跳離此迴圈。

    last 敘述

    last 用於跳離迴圈,不再執行該迴圈,通常會和 if 搭配使用。如下例:

    for (my $i = 10; $i > 0; $i--) {
        last if $i <= 5;
        
        print "Count down $i\n";
    }
    

    goto 敘述

    goto 不限於迴圈中使用,可跳到程式中任意位置。下例用 goto 模擬 while 迴圈:

    my $n;
    
    RESTART:
    $n = int(rand(10)) + 1;
    $n % 2 == 0 or goto RESTART;
    
    print $n, "\n";
    

    在這個程式中,當 $n 不為偶數時,就跳到 RESTART 所在的地方。可以和先前 redo 的版本相互比較。

    濫用 goto 會造成程式難以維護,故現在較少使用 goto 而會使用前述的 nextredolast 等。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Yahoo
    【追蹤本站】
    Facebook Facebook Twitter Parler