程式扎記: [ Ruby Gossip ] Basic : 流程控制 - while、until、loop 與 for

標籤

2014年10月18日 星期六

[ Ruby Gossip ] Basic : 流程控制 - while、until、loop 與 for

Source From Here 
Preface 
Loops in Ruby are used to execute the same block of code a specified number of times. This chapter details all the loop statements supported by Ruby. 

while、until、loop 與 for 
while 迴圈根據所指定的條件式來判斷是否執行迴圈本體,例如以下是個求最大公因數的程式: 
  1. # encoding: Big5  
  2. puts "輸入兩個數字..."  
  3. m = gets.to_i  
  4. n = gets.to_i  
  5. while n != 0  
  6.    r = m % n  
  7.    m = n  
  8.    n = r  
  9. end  
  10. puts "GCD: #{m}"   
while 迴圈為前測式迴圈,因為它在迴圈執行前就會進行條件判斷,而 begin...while 為後測式迴圈,它會先執行迴圈本體,然後再進行條件判斷,例如: 
  1. # encoding: Big5  
  2. begin  
  3.     print "輸入數字:"  
  4.     printf "輸入數為 %s\n", gets.to_i % 2 == 0 ? "偶數" : "奇數"  
  5.     print "繼續?(Yes/No)"  
  6. end while gets.chomp == "Yes"  
while 還有個行內用法,例如以下程式可取得隨機偶數: 
  1. n = 1  
  2. n = (rand() * 10).to_i while n % 2 == 1  
  3. print n  
與 while 相反的是 until,while 是條件式成立時,執行迴圈本體,until 是直到條件式成立前,都要執行迴圈本體。例如先前求最大公因數的程式,可以改為: 
  1. # encoding: Big5  
  2. puts "輸入兩個數字..."  
  3. m = gets.to_i  
  4. n = gets.to_i  
  5. until n == 0  
  6.    r = m % n  
  7.    m = n  
  8.    n = r  
  9. end  
  10. puts "GCD: #{m}"  
until 也可以先執行迴圈本體,再測試條件式成立與否。例如: 
  1. # encoding: Big5  
  2. begin  
  3.     print "輸入數字:"  
  4.     printf "輸入數為 %s\n", gets.to_i % 2 == 0 ? "偶數" : "奇數"  
  5.     print "繼續?(Yes/No)"  
  6. end until gets.chomp == "No"  
until 也可以用行內寫法。例如: 
  1. n = 1  
  2. n = (rand() * 10).to_i until n % 2 != 1  
  3. print n  
如果想要無窮執行迴圈,可以使用 loop 方法。例如: 
  1. # encoding: Big5  
  2. loop { print "永不停止的 Orz..." }  
loop 是個方法,就像使用數值的 times 方法一樣,必須使用區塊指定執行內容;數值的 times 方法,也常用在指定次數的迴圈。例如: 
  1. # encoding: Big5  
  2. 10.times do |i|  
  3.     puts "第 #{i + 1} 次的 Orz..."  
  4. end  
先前 陣列型態 談過,可以使用陣列的 each 方法逐一取得元素,也可以使用 for 逐一取得陣列元素: 
  1. # encoding: Big5  
  2. [12345].each do |element|  
  3.     print element  
  4. end  
  5. puts  
  6. for element in [12345]  
  7.     print element  
  8. end  
事實上,只要物件上有 each 方法,就可以使用 for,for 其實是利用了 each 方法的語法,正確來說,each 是迭代器之後會說明迭代器的撰寫方式),先前談過的 loop、times 方法也是迭代器。無論是 while、until、for 或是迭代器,都可以搭配 break、next 與 redo 來控制流程。例如: 
  1. # encoding: Big5  
  2. loop do  
  3.     print "輸入數字:"  
  4.     number = gets.to_i  
  5.     printf "輸入數為 %s\n" % (number % 2 == 0 ? "偶數" : "奇數")  
  6.     print "繼續?(Yes/No)"  
  7.     if gets.chomp == "No"  
  8.         break  
  9.     end  
  10. end  
break 可用於中斷目前迴圈或迭代器的執行,next 則會直接進行「下一次迴圈」,。例如: 
  1. # 底下顯示 1234  
  2. for i in 1..9  
  3.     if i == 5  
  4.         break  
  5.     end  
  6.     print i  
  7. end  
  8. puts  
  9. # 底下顯示 12346789  
  10. for i in 1..9  
  11.     if i == 5  
  12.         next  
  13.     end  
  14.     print i  
  15. end  
第一段 for 程式會顯示1到4,因為當i 等於5時就會執行 break 而離開迴圈;第二段 for 程式會顯示1到4,然後是6到9,當 i 等於 5 時,會執行 next 直接進行下一次迴圈,這次迴圈print該行並沒有被執行,所以5並沒有被顯示。 

redo是重作「一次redo前的區塊內容」(不是重作「一次迴圈」)。例如: 
  1. # 底下顯示 1234redoredoredo....  
  2. for i in 1..9  
  3.     if i == 5  
  4.         print "redo"  
  5.         redo  
  6.     end  
  7.     print i  
  8. end  
redo 並沒有重作一次迴圈,而是重作一次 redo 前的區塊內容,因此上例 i 等於 5 時,並沒有進行 for 該行設定 i 的動作,而是重作一次 for 該行之後的區塊,所以i一直都會是5,然後符合 if 條件而不斷redo。 

Supplement 
Ruby 手冊 - 控制結構 
Ruby tutorialspoint - Ruby Loops - while, for, until, break, redo and retry

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!