開放原始碼技術文件網 迭代控制結構 (Iteration Control Structures)

最後修改日期為 SEP 7, 2020

前言

迭代 (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