[ C++ ] While 迴圈與 do-While 迴圈用法及使用時機
C++ 中,有提供 While 迴圈(While loop), 與 do-While 迴圈兩種,While loop 為前測式迴圈,而 do-While loop 為後測式迴圈,雖然是基本迴圈,但也是初學者最容易誤解,最容易寫錯的迴圈,本文將詳細講解 While loop 與 do-While loop 的定義,用法,分別,使用時機,及常犯錯誤。
先備知識等級: 須先了解 for 迴圈及其應用
約需花 20 分鐘閱讀
{{目錄}}
使用 while 迴圈時的 使用 do-while 迴圈時的
由於會在進入迴圈前判斷條件,因此稱為前測式迴圈
While loop 的語法:
while ( condition ) statement
while ( 條件 ) 陳述句
注意,雖然在 C++ 的定義中 while loop 是不帶 { } 的,但學校通常都是教 while ( condition ) { statement } ,這是因為通常 statement 的部分會超過 1 句陳述句,若沒有 { },則 while 會以 condition 後的第一句陳述句為迴圈本體(loop body)。所以如果我們將上方 while 迴圈中的 { } 拿掉:
雖然這段程式碼可以編譯成功,但卻隱藏了一個邏輯錯誤。因為當此 while loop 執行時,只會將 j ++; 視為 loop body ,因此 i ++; 將不會被讀到 (讀到 j ++ 後程式就回到開頭去判斷條件),而因為 i ++; 沒有被讀到,所以 i 的值將永遠等於 0;意味著條件永遠成立(因為 0 恆小於 3),程式便卡在這個迴圈中無法跳出,此 loop 就成為了一個無窮迴圈 (infinite loop) ,而這種錯誤往往難以被察覺。
上圖可以看出,雖然 GCC 編譯成功,但真正執行時,程式卻會卡住而無法繼續(並且由於產生了無窮迴圈,導致 j 的值正在不斷的增加)。因此,使用 while loop 時,請養成使用 { } 的好習慣(事實上寫任何迴圈都應該要養成這個習慣),並確保 loop body 不會造成無窮迴圈,除非那是你的目的。
While loop 的使用時機:
常用但不限於
1.需要重複判斷,且無法估算需要判斷的次數
例如:臺灣手機號碼格式必須為 09 開頭,且總共為 10 個數字。假如你今天寫了一個讀取手機號碼的程式,由於你無法保證不會有小屁孩故意輸入 12345678,或是 ABCDEFGH,且一直持續這樣玩,所以這時就適合用 while 迴圈,則不管他輸入幾次,只有格式正確時程式才會進到下一步。
2.在某個事件發生前,盡可能地執行某個動作
例如:在達到當月的網路流量限制前,儘可能的下載檔案。 就算你並不知道當月流量限制是多少,但 While 迴圈則可以保證只有在流量恰好到達上限時,檔案才會停止下載。
下面介紹 do-while loop
由於條件是在迴圈內容運行完之後才判斷,因此又稱為後測式迴圈,其特色就是在判斷條件前,會先執行迴圈內容
do-while loop 的語法:
do statement while ( condition ) ;
do 陳述 while ( 條件 ) ;
和 while 一樣,在撰寫 statement 時,需要養成 { } 的好習慣。值得一提的是, do-while loop 的後面必須要加上 ; ,因為 do-while loop 的結尾不是 } ,需要加上一個 ; 來表示語句結束,這也是新手常忘記的細節。
而另一個需要注意的重點是: 即便條件式在一開始就不成立,do-while loop 仍然會執行至少一次,因為他是在執行完迴圈本體後,才判斷條件;因此就算呼叫迴圈時條件是不成立的,程式在執行一次迴圈本體後才會知道。
do-while loop 的使用時機:
雖然幾乎所有 do-while loop 都可以用 while loop 來重現,但有些情況下,使用 do-while loop 能夠更直覺地呈現出程式的流程,甚至使程式更有效率。
常用但不限於
1. 需要先進行某種動作後,再確認條件是否成立
例如我想寫一個檢查電子錢包餘額的程式,來確認買家的商品款是否匯入,且直到款項匯入前,這個程式將會一直提醒我款項尚未匯入,使用 do-while loop 的程式思路如下
注: 由於迴圈只有在條件成立時才會繼續執行,而我們希望在餘額未增加時可以持續地跑這個迴圈,
因此條件須設置為 "餘額未增加 "
餘額未增加(成立) --> 餘額未增加
餘額未增加(不成立) --> 餘額已增加
假設今天是使用 while loop,則程式流程會變成下圖
不難發現,由於 while loop 前測式的性質,我們需要先存取一次電子錢包,才能進行第一次條件的判斷,又因為 while loop 的 loop body 是在條件判斷之後,導致我們在迴圈中利用前面的程式碼,必須要在 loop body 內再執行一次存取,才能使下一次迴圈有可以判斷的條件;也就是說,使用 while loop 的話,比起 do-while loop 會需要額外存取資料庫一次。
假設今天存取一次需要一段時間(如 20 秒),並且程式中需要多次進行判斷的話,此時使用 while loop 執行起來將會比 do-while loop 花上更多的時間。身為程式設計者,當然必須選擇相對效率較高的寫法。
下面就用 C++ 來模擬電子錢包的例子: 假設迴圈執行到第三次時,款項將會匯入
我們同時利用 while loop 與 do-while loop 來模擬檢查餘額的程式
do-while loop:
while loop:
可以看出,使用 while loop 時確實會需要多存取一次錢包,
且因為 while loop 在執行完迴圈後,還會再回頭進行條件判斷,因此會比 do-while多判斷一次,但兩種迴圈本體的執行次數都是 3 次
*若需要錢包模擬程式的原始碼請寄電子郵件至 Ching91203@gmail.com (點擊此連結可直接進入郵件),並說明需要有關 while_do-while loop 的範例程式碼
參考:
https://www.cprogramming.com/tutorial/lesson3.html
https://www.w3schools.com/cpp/cpp_while_loop.asp
https://www.w3schools.com/cpp/cpp_do_while_loop.asp
https://www.geeksforgeeks.org/c-c-while-loop-with-examples/
https://en.cppreference.com/w/cpp/language/do
https://en.cppreference.com/w/cpp/language/statements
https://en.cppreference.com/w/cpp/language/expressions
https://stackoverflow.com/questions/3003456/why-use-a-do-while-loop
https://stackoverflow.com/questions/994905/is-there-ever-a-need-for-a-do-while-loop
https://www.tutorialspoint.com/cplusplus/cpp_loop_types.htm
https://www.cs.utah.edu/~germain/PPS/Topics/while_loops.html
留言列表