程式迴圈
出自 MBA智库百科(https://wiki.mbalib.com/)
目錄 |
程式迴圈是電腦科學運算領域的用語,也是一種常見的控制流程。迴圈是一段在程式中只出現一次,但可能會連續運行多次的代碼。迴圈中的代碼會運行特定的次數,或者是運行到特定條件成立時結束迴圈,或者是針對某一集合中的所有項目都運行一次。
在一些函數編程語言(例如Haskell和Scheme)中會使用遞歸或不動點組合子來達到迴圈的效果,其中尾部遞歸是一種特別的遞歸,很容易轉換為迭代。
大部分編程語言都提供迴圈的指令,可以依指定的次數重覆運行一段程式。若指定的次數N小於1,編程語言會忽略整個迴圈不去運行,若指定的次數N為1,則迴圈只會運行一次。在迴圈進行時,迴圈計數器也會隨著變化,大部分的編程語言可以允許迴圈計數器上數或是下數,每次的變化量可以是1或是其他不為0的數值。
大多數的編程語言都有指令,可以在特定條件成立時繼續迴圈的進行,或是特定條件不成立時繼續迴圈的進行,進行到特定條件成立為止。前者一般會標示while,後者一般會標示until。其判斷條件可能在迴圈一開始就進行,或是在迴圈最後才進行。前者的迴圈不一定會運行,而後者1的迴圈至少會運行一次。
許多編程語言支持一種特別的迴圈,可以針對一個數組中的元素或是一個集合中的所有成員進行迴圈中的指令,包括Ada、D語言、Smalltalk、Perl、Java、C#、Visual Basic、Ruby、Python、JavaScript、Fortran 95等編程語言都有這類的迴圈結構。
有些編程語言有泛用迴圈結構,可以用來表示指定次數或指定條件的迴圈,像C語言的for指令或是Common Lisp語言中的do指令都是這類的例子,不過為了程式的可讀性考量,在這些編程語言中還是儘量使用一些含義較明確的指令(如while指令)。
死迴圈一般會用在有一段程式需要永遠運行,或是該程式在沒有發生特殊事件(如故障)時需要永遠運行的場合,例如一個事件驅動的程式需要持續運行迴圈,處理髮生的事件,直到用戶結束或中斷程式為止。若在指定條件的迴圈中,其判斷條件用到的變數數值永遠不會改變,這種程式錯誤也會使得此迴圈變成死迴圈。
當使用指定次數的迴圈查表時,會希望在查到需要的數據時就可以直接結束迴圈的進行,有些編程語言可以用break或exit的指令達到這様的功能,這些指令會結束這個迴圈,接著會運行迴圈後面的指令。若此迴圈在副程式中,也可以用return中斷迴圈的進行,同時離開副程式。
有時在使用迴圈的程式中會希望在特定情形下跳過目前迴圈區塊的指令,回到迴圈開始運行下一個迴圈,一般這類的指令會命名為continue、skip或next,其效果是提早結束這次迴圈的進行,繼續進行下一個迴圈,若此迴圈已經是最後一次運行,這類指令會結束迴圈的進行,繼續進行後續的指令。
像Perl及Ruby等編程語言有redo指令,可以重新運行目前的迴圈,若在指定次數的迴圈中,其迴圈計數器的數值不會變化。Ruby編程語言有retry指令,可以讓迴圈計數器回到初值,重新運行整個迴圈。
迴圈變式(Loop variant)及迴圈不變式(Loop invariant)是判斷迴圈正確性的工具。迴圈變式是一個初值不為負的整數表示式,在每次運行迴圈時迴圈變式的數值需減少,但在正常的迴圈運行過程中迴圈變式的數值不會變成負值。迴圈變式用來確保迴圈會結束。 迴圈不變式是一個和迴圈有關的判斷式,在第一次進入迴圈之前,迴圈不變式的值需為真,在後續每一次運行迴圈時,其值也要為真。當迴圈正確的結束時,其終止條件和迴圈不變式都會成立。迴圈不變式可用來監控在迴圈進行時,某一指定性質的狀態。
像是Eiffel之類的編程語言本身就有支持迴圈變式及迴圈不變式,其他語言可能需要有附加組件才能支持此功能,例如Java就需要配合Java建模語言(Java Modeling Language)規範的loop statements才能支持此機能。