本章我們會(huì)講述:
- 程序中的循環(huán)是什么
- 寫(xiě)循環(huán)時(shí)需要注意什么
- 循環(huán)的種類(lèi)及其寫(xiě)法
6.1 循環(huán)的基礎(chǔ)
6.2循環(huán)的注意事項(xiàng)
- 循環(huán)的主體是什么
- 停止循環(huán)的條件是什么
6.3 實(shí)現(xiàn)循環(huán)的方法
Ruby中有兩種實(shí)現(xiàn)循環(huán)的方法
- 使用循環(huán)語(yǔ)句
利用 Ruby 提供現(xiàn)有的循環(huán)語(yǔ)句,可以滿(mǎn)足大部分循環(huán)處理的需求。 - 使用方法實(shí)現(xiàn)循環(huán)
將塊傳給方法,然后在塊里面寫(xiě)上需要循環(huán)的處理。一般我們?cè)跒榱四撤N特定目的而需要定制循環(huán)結(jié)構(gòu)時(shí),才使用方法來(lái)實(shí)現(xiàn)循環(huán)。 下面是我們接下來(lái)要介紹的六種循環(huán)語(yǔ)句或方法。- times方法
- while語(yǔ)句
- each方法
- for語(yǔ)句
- until語(yǔ)句
- loop方法
6.4 times 方法
如果只是單純執(zhí)行一定次數(shù)的處理,用 times 方法可以很輕松實(shí)現(xiàn)。 假設(shè)我們希望把“滿(mǎn)地油菜花”這個(gè)字符串連續(xù)輸出 7 次。
7.times do
puts "滿(mǎn)地油菜花"
end
執(zhí)行示例:
ruby times.rb
滿(mǎn)地油菜花
滿(mǎn)地油菜花
滿(mǎn)地油菜花
滿(mǎn)地油菜花
滿(mǎn)地油菜花
滿(mǎn)地油菜花
滿(mǎn)地油菜花
使用 times 方法實(shí)現(xiàn)循環(huán)時(shí),需要用到塊 do ~ end。
循環(huán)次數(shù).times do
希望循環(huán)的處理
end
塊的do ~ end部分可以用 {~}代替,即
循環(huán)次數(shù).times {
希望循環(huán)的處理
}
6.5 for 語(yǔ)句
for 語(yǔ)句同樣是用于實(shí)現(xiàn)循環(huán)的。需要注意的是,與剛才介紹的 times 方法不同,for 并不是方法,而是 Ruby 提供的循環(huán)控制語(yǔ)句。
代碼清單 6.4 for.rb
sum = 0
for i in 1..5
sum = sum + i
end
puts sum
執(zhí)行示例:
ruby for.rb
15
for 語(yǔ)句的結(jié)構(gòu):
for 變量in開(kāi)始時(shí)的數(shù)值..結(jié)束時(shí)的數(shù)值 do
希望處理的循環(huán)
end
可以省略do
6.6 普通的for語(yǔ)句
for 變量 in 對(duì)象 do
希望循環(huán)的處理
end
下面是使用數(shù)組對(duì)象的例子。
names = ["awk", "Perl", "Python", "Ruby"]
for name in names
puts name
end
6.7 while 語(yǔ)句
不管哪種類(lèi)型的循環(huán),while 語(yǔ)句都可以勝任,while 語(yǔ)句的結(jié)構(gòu)如下:
while 條件 do
希望循環(huán)的處理
end
6.8 until語(yǔ)句
與 if 語(yǔ)句相對(duì)的有 unless 語(yǔ)句,同樣地,與 while 語(yǔ)句相對(duì)的有 until 語(yǔ)句。until 語(yǔ)句的結(jié)構(gòu)與 while 語(yǔ)句完全一樣,只是條件判斷剛好相反,不滿(mǎn) 足條件時(shí)才執(zhí)行循環(huán)處理。換句話(huà)說(shuō),while 語(yǔ)句是一直執(zhí)行循環(huán)處理,直到條件不成立為止;until 語(yǔ)句是一直執(zhí)行循環(huán)處理,直到條件成立為止。
until 條件 do
希望循環(huán)的處理
end
雖然可以使用 while 語(yǔ)句的否定形式代替 until 語(yǔ)句。但是,有時(shí)對(duì)一些比較復(fù)雜的條件表達(dá)式使用否定,反而會(huì)不直觀,影響程序理解,在這種情況下, 我們應(yīng)該考慮使用 until 語(yǔ)句。
6.9 each 方法
each 方法將對(duì)象集合里的對(duì)象逐個(gè)取出,這與 for 語(yǔ)句循環(huán)取出數(shù)組元素非常相似。實(shí)際上,我們可以非常簡(jiǎn)單地將使用 for 語(yǔ)句的程序(代碼清單 6.5) 改寫(xiě)為使用 each 方法的程序(代碼清單 6.11)。
代碼清單 6.11 each_names.rb
names = ["awk", "Perl", "Python", "Ruby"]
names.each do |name|
puts name
end
each 方法的結(jié)構(gòu)如下:
對(duì)象.each do |變量|
希望循環(huán)的處理
end
塊的 do ~ end 部分可換成 { ~ }。
這與下面的程序的效果是幾乎一樣。
for 變量 in 對(duì)象
希望循環(huán)的處理
end
在 Ruby 內(nèi)部,for 語(yǔ)句是用 each 方法來(lái)實(shí)現(xiàn)的。因此,可以使用 each 方法的對(duì)象,同樣也可以指定為 for 語(yǔ)句的循環(huán)對(duì)象。 在介紹 for 語(yǔ)句時(shí)我們舉過(guò)使用范圍對(duì)象的例子(代碼清單 6.4),我們?cè)囍?each 方法改寫(xiě)一下。
代碼清單 6.12 each.rb
sum = 0
(1..5).each do |i|
sum = sum + i
end
puts sum
像本例這樣,我們可以輕松互相改寫(xiě)兩種用法。那到底什么時(shí)候該用 for 語(yǔ)句,什么時(shí)候該用 each 方法呢,我們將在本章的最后討論這個(gè)問(wèn)題。
6.10 loop 方法
還有一種循環(huán)的方法,沒(méi)有終止循環(huán)條件,只是不斷執(zhí)行循環(huán)處理。Ruby 中的 loop 就是這樣的循環(huán)方法。
loop do
print "Ruby"
end
執(zhí)行上面的程序后,整個(gè)屏幕會(huì)不停的輸出文字 Ruby。為了避免這樣的情況發(fā)生,在實(shí)際使用 loop 方法時(shí),我們需要用到接下來(lái)將要介紹的 break,使程 序可以中途跳出循環(huán)。
6.11 循環(huán)控制
break 終止程序,跳出循環(huán)
next 跳到下一次循環(huán)
redo 在相同的條件下重復(fù)剛才的處理
另外,大家要注意 redo 的使用方法,稍不留神就會(huì)在同樣的條件下,不斷地重復(fù)處理,陷入死循環(huán)中。 break、next 和 redo 中,一般比較常用是 break 和 next。大家應(yīng)該熟練掌握這兩個(gè)命令的用法。即使是 Ruby 默認(rèn)提供的庫(kù)里面,實(shí)際上也很難找到 redo 的蹤影,所以當(dāng)我們?cè)谙M褂?redo 時(shí),應(yīng)該好好考慮是否真的有必要使用 redo。
6.12 總結(jié)
如果純粹只考慮實(shí)現(xiàn)循環(huán)功能,任何種類(lèi)的循環(huán)都可以用 while 語(yǔ)句實(shí)現(xiàn)。講得極端一點(diǎn),其他循環(huán)語(yǔ)句和方法根本也沒(méi)存在的必要。即便如此,那為什么 Ruby 還提供了那么豐富的循環(huán)語(yǔ)句和方法呢。這是因?yàn)椋绦虿⒉恢皇菃渭優(yōu)榱藢?shí)現(xiàn)功能,同時(shí)還應(yīng)該使代碼更便于讀寫(xiě),使人更容易理解。
下面我們簡(jiǎn)要介紹一下各種循環(huán)應(yīng)在何時(shí)使用:
times 方法 確定循環(huán)次數(shù)時(shí)使用
for 語(yǔ)句 從對(duì)象去除元素時(shí)使用(each的語(yǔ)法糖)
while 語(yǔ)句 希望自由指定循環(huán)條件時(shí)使用
until 語(yǔ)句 使用while語(yǔ)句使循環(huán)變得難懂時(shí)使用
each 方法 從對(duì)象取出元素時(shí)使用
loop 方法 不限制循環(huán)次數(shù)時(shí)使用
PS:語(yǔ)法糖(syntax sugar),是指一種為了照顧一般人習(xí)慣而產(chǎn)生的特殊語(yǔ)法 1。例如,使用常規(guī)的語(yǔ)法調(diào) 用方法,那么加法運(yùn)算應(yīng)該寫(xiě)成 3.add(2)。 但是對(duì)于一般人來(lái)說(shuō),寫(xiě)成 3 + 2 會(huì)更直觀,更簡(jiǎn)明易懂。 語(yǔ)法糖并不會(huì)加強(qiáng)編程語(yǔ)言的任何功能,但是對(duì)于提高程序的易讀性來(lái)講是不可或缺的。
確定循環(huán)次數(shù)時(shí)循環(huán)處理使用 times 方法,除此以外的大部分循環(huán)處理,根據(jù)情況選擇 while 語(yǔ)句或者 each 方法,一般也能寫(xiě)出直觀易懂的程序。請(qǐng)大家 先熟練掌握這三種循環(huán)方法。
do~end 與 {~}
在 times 方法的示例中,我們介紹了塊的兩種寫(xiě)法,do ~ end 與 { ~ }。從執(zhí)行效果來(lái)看,兩種方法雖然沒(méi)有太大區(qū)別,但一般我們會(huì)遵守以下這 個(gè)約定俗成的編碼規(guī)則:
- 程序是跨行寫(xiě)的時(shí)候使用 do ~ end。
- 程序?qū)懺?1 行的時(shí)候用 { ~ }。
例如:
10.times do |i|
puts i
end
or
10.times{|i| puts i
剛開(kāi)始大家可能會(huì)有點(diǎn)不習(xí)慣。我們可以這樣理解,do ~ end 表示程序要執(zhí)行內(nèi)容是多個(gè)處理的集合,而 { ~ } 則表示程序需要執(zhí)行的處理只有一 個(gè),即把整個(gè)帶塊的方法看作一個(gè)值。
如果用把 do ~ end 代碼合并在一起,程序會(huì)變成下面這樣:
10.times do |i| puts i end
以上寫(xiě)法,怎么看都給人一種很難斷句的感覺(jué)。雖然實(shí)際上使用哪種寫(xiě)法都不會(huì)影響程序的運(yùn)行,但在剛開(kāi)始編寫(xiě)程序時(shí),還是建議大家先遵守這個(gè)編 碼規(guī)則。