## 5.循環
有時你可能需要執行一些重復性的任務,比如說我想編寫一個火箭倒計時程序,我想創建一個自動為火箭倒數的機器人,當計數結束時會說“ Blast Off”,讓我們寫一個 看看
```rb
# count_down.rb
# Zigor tells about itself
puts "Hello, I am Zigor...."
puts "I count down for rockets"
# Count down starts
puts 10
p 9 # p is a short form for puts
p 8
p 7
p 6
p 5
p 4
p 3
p 2
p 1
p "Blast Off!"
```
好吧,希望你能理解上面的程序。 我想說明的是,`p`是`puts`的一種簡短形式,不用寫`puts`就能使用`p`并得到相同的結果 <sup class="footnote">[ [16 [](#_footnotedef_16 "View footnote.") ]</sup> 。 上面的程序在運行時顯示以下內容
```rb
Hello, I am Zigor....
I count down for rockets
10
9
8
7
6
5
4
3
2
1
"Blast Off!"
```
如此完美的執行,但是我們可以提高代碼的效率,我們很快就會看到
### 5.1。 向下
在你的文本編輯器中,鍵入以下程序
```rb
# count_down_1.rb
# Zigor tells about itself
puts "Hello, I am Zigor...."
puts "I count down for rockets"
# Count down starts
10.downto 1 do |num|
p num
end
p "Blast Off!"
```
運行它,看看。 好了,你的程序現在使用了更少的代碼,但是卻產生了相同的結果!
注意事情`10.downto 1`,該語句使 Zigor 從 10 倒數到 1,而在倒數的同時,你可以使用倒數值做一些事情,還可以在循環塊中放入一些代碼。 循環以`do`開始,并在遇到`end`命令時結束。 你輸入的任何代碼都應介于`do`和`block` <sup class="footnote">[ [17](#_footnotedef_17 "View footnote.") ]</sup> 之間
```rb
10.downto 1 do
# do some thing! Anything!!
end
```
因此,可以在`do`和`end`(技術上稱為塊)之間放置代碼以打印倒數。 首先如何獲得號碼? 我們將在名為`num`的變量中獲取它,因此我們將代碼重寫為如下所示
```rb
10.downto 1 do |num|
# put the printing stuff here
end
```
上面請注意,`num`被`|`和`|`包圍。 現在我們需要做的就是打印它,所以我們只打印如下圖所示
```rb
10.downto 1 do |num|
p num
end
```
### 5.2。 次
times 是一個非常簡單的循環,如果你想讓代碼執行 N 次,則將代碼放入其中。 現在讓我們看看 Zigor 知道什么
```rb
# times.rb
puts "Hi, I am Zigor"
puts "I am going to tell what I know"
7.times{
puts "I know something"
}
```
好了,執行后程序會打印以下內容
```rb
Hi, I am Zigor
I am going to tell what I know
I know something
I know something
I know something
I know something
I know something
I know something
I know something
```
Zigor 告訴它它知道七次。
好的,我們已經在程序中進行了更改,這次我們將打印 count 變量,在下面鍵入程序并執行
```rb
# times_1.rb
puts "Hi, I am Zigor"
puts "I am going to tell what I know"
7.times{ |a|
puts "#{a}. I know something"
}
```
這就是你得到的結果
```rb
Hi, I am Zigor
I am going to tell what I know
0\. I know something
1\. I know something
2\. I know something
3\. I know something
4\. I know something
5\. I know something
6\. I know something
```
為什么從零數到六而不是一七呢? 好吧,如果一切按你的意愿進行,那么就不需要像你和我這樣的程序員了,所以不要打擾。 請注意,在這些程序中,我們使用`{`和`}`,而不是 do and end。 好吧,Ruby 鼓勵使用不同的編程風格。
### 5.3。 取決于
`upto`將從某個數字數到另一個數字。 就像倒過來一樣。 輸入以下程序并執行
```rb
# upto.rb
# upto is downto in reverse
17.upto 23 do |i|
print "#{i}, "
end
```
這是輸出的樣子
```rb
17, 18, 19, 20, 21, 22, 23,
```
### 5.4。 步
可以將`step`循環視為`upto`和`downto`的組合,將它們打包在一起,執行以下代碼
```rb
# step_1.rb
# explains step function
1.step 10 do |i|
print "#{i}, "
end
```
這就是結果。 這與`upto`非常相似! 你沒看到!!
```rb
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
```
現在,如下所示修改程序并將其保存為其他名稱
```rb
# step_2.rb
# explains step function
10.step 1 do |i|
print "#{i}, "
end
```
執行該程序時不產生任何輸出。 我們做錯了什么? 如下所示修改程序并運行
```rb
# step_3.rb
# explains step function
# this time its stepping down
10.step 1, -1 do |i|
print "#{i}, "
end
```
好了,這是程序的輸出
```rb
10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
```
接下來會發生什么? 步驟接收三個輸入,請考慮以下代碼
```rb
10.step 1, -1
```
第一個是將調用步驟的號碼作為初始號碼,在上述情況下為`10`。 在這種情況下,下一個是結束號,即`1`,即此函數從 10 到 1 計數,在這種情況下,我們必須遞減,因此計數必須以`-1`為步長。
我可以修改同一程序,以 10 到 1 的方式打印偶數,如下所示
```rb
# step_4.rb
# explains step function
# this time its stepping down
p "Even numbers between 10 and 1:"
10.step 1, -2 do |i|
print "#{i}, "
end
```
該程序輸出以下輸出
```rb
“Even numbers between 10 and 1:”
10, 8, 6, 4, 2,
```
現在讓我們嘗試一個程序,該程序將按升序打印從 1 到 10 的偶數
```rb
# step_4.rb
# explains step function
# this time its stepping upby two counts each loop
p "Even numbers between 1 and 10:"
2.step 10, 2 do |i|
print "#{i}, "
end
```
輸出量
```rb
“Even numbers between 1 and 10:”
2, 4, 6, 8, 10,
```
在上面的代碼中,從 2 開始,我們將在 10 結束,然后以 2 的步長跳過每個循環。在循環內部,我們僅打印在變量`i`中捕獲的迭代值。
### 5.5。 而
盡管 <sup class="footnote">[ [18](#_footnotedef_18 "View footnote.") ]</sup> 循環是一個循環,直到滿足條件為止。 閱讀下面的代碼
```rb
# while.rb
i=1
while i<=10 do
print "#{i}, "
i+=1
end
```
執行后,將產生以下輸出。
```rb
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
```
現在讓我們看看 while 循環是如何工作的。 While 循環通常包含四個重要部分
1. 初始化
2. 條件檢查
3. 圈體
4. 更新中
**初始化**
參見語句`i=1`,在這里我們初始化名為`i`的變量并將其設置為`1`值。
**條件檢查**
參見語句`while i?10`,在該語句中,我們指定我們開始一個 while 循環,每次迭代時,該 while 循環都會檢查`i`的值,如果其小于或等于`10`,則循環主體會盲目地 被執行。
**環體**
注意程序中的`do`和`end`,`do`代表循環代碼塊的開始,`end`代表循環代碼塊的結束。 在它們之間,我們有一些陳述,我們將很快討論。 聲明之一是打印`i`的值,該值由`print "#{i}, "`完成
**更新**
假設我們忘了在循環體中包含`i+=1`,在每次迭代結束時,`i`的值將始終保持為 1,而我將始終保持小于 10,因此循環將被執行無數次,并且 將打印無限的 1。 實際上,你的程序將崩潰,并可能導致不良后果。 為了避免這種情況,我們必須包含更新聲明。 在這里,我們放置了`i+=1`,它在每次迭代繼續時將`i`的值增加一,這確保`i?10`在某個階段變為`false`,因此循環停止執行 <sup class="footnote">[ [19 [](#_footnotedef_19 "View footnote.") ]</sup> 。
因此,我們看到,為了使循環以理想的方式工作,我們需要使這四個部分交響。
### 5.6。 直到
`while`循環持續進行直到條件變為`false`,直到循環持續進行直到條件變為`true`。 閱讀下面的代碼,在文本編輯器中鍵入并執行它。
```rb
# until.rb
i=1
until i>10 do
print "#{i}, "
i+=1
end
```
這就是你將得到的結果
```rb
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
```
那么這個循環如何工作? 首先,我們設置`i=1`,然后使用直到命令`i`大于 10 之前,請在此行`until i>10 do`中繼續執行操作。 在`do`和`end`關鍵字之間說了些什么。 因此,直到條件失敗,循環主體中的代碼將被執行,因此我們將輸出 1 到 10。
### 5.7。 打破
假設你想脫離循環,也就是停止執行循環,可以使用`break`命令。 下面給出一個例子。 在示例中,如果迭代變量`i`變為 6,我們將中斷操作。因此,僅輸出 1 到 5 范圍內的數字。 當`i`變為 6 時,循環中斷或終止
```rb
#break.rb
1.upto 10 do |i|
break if i == 6
print "#{i}, "
end
```
執行后,上面的程序產生以下輸出
```rb
1, 2, 3, 4, 5,
```
### 5.8。 下一個
`break`,退出循環并終止。 `next`與`break`有所不同,它不是中斷循環,而是繼續循環而不執行`next`之后發生的語句的信號。 這是一個供你理解的示例
```rb
# next.rb
# This loop won't print 6
10.times do |num|
next if num == 6
puts num
end
```
Output
```rb
0
1
2
3
4
5
7
8
9
```
如果你注意到輸出,則看到打印了從 0 到 9 的數字,但沒有打印出 6。請注意 [next.rb](code/next.rb) 中的`next if num == 6`行,如果`num`為`6`,`next`被執行,換言之`do` `end`塊之后的所有行均被跳過。 與`brake`不同,循環不會終止,而是僅跳過`next`之后的行,循環繼續進行。
### 5.9。 重做
還有另一件事`redo`。 `next`進一步跳過任何執行,并且迭代變量遞增/遞減到下一個可能的值 <sup class="footnote">[ [20](#_footnotedef_20 "View footnote.") ]</sup> ,另一方面,`redo`跳過循環塊中代碼的進一步執行 ,但迭代變量不會增加,而是重新運行循環。 輸入以下代碼并執行
```rb
# redo.rb
5.times do |num|
puts "num = #{num}"
puts "Do you want to redo? (y/n): "
option = gets.chop
redo if option == 'y'
end
```
運行它,希望你可以自己解釋;-)
### 5.10。 環
因此,到目前為止,我們已經看到了許多類型的循環,但是我省略了一個稱為`loop`的基本循環。 為什么我忽略了它,因為使用 <sup class="footnote">[ [21](#_footnotedef_21 "View footnote.") ]</sup> 危險。 好吧,讓我們看一個例子。 在下面鍵入程序并執行。 請注意,你需要按 Ctrl + C 才能停止執行。 所以要小心一點
```rb
# loop.rb
loop do
puts "I Love Ruby"
end
```
```rb
Output
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
I Love Ruby
......
```
輸出將繼續打印`I Love Ruby`,直到你按 Ctrl 和 C 鍵使輸出斷開為止。 基本是這樣的:循環執行和結束之間的任何操作都將繼續進行。
現在讓我們說我們不希望這個循環永遠持續運行。 讓我們看看如何馴服它。 讓我們打印一個可以打印 1 到 10 的程序。在下面鍵入該程序并運行。
```rb
# break_at_10.rb
i = 1
loop do
puts i
break if i == 10
i = i+1
end
```
Output
```rb
1
2
3
4
5
6
7
8
9
10
```
因此,程序可以按我們希望的那樣打印 1 到 10。 讓我們來看看它如何工作。 第一行`i = 1`將值`1`存儲在名為`i`的變量中。 接下來,我們有這條`loop do`行,在這行和`end`之間放置的任何東西都將連續運行。
在下一行`puts i`中,我們打印`i`的值,因此打印了`1`,現在在`break if i == 10`中,它檢查`i`是否為 10,此處的條件是`false`為`i` 不是 10,因此循環將繼續到下一個語句`i = i + 1`,我們將`i + 1`中的`i`加 1,因此它變成 2,因此通過說`i = i + 1`表示`i = 1 + 1`,因此`i`將 變為 2 并且它(程序)符合`end`語句,這并不意味著 end,它僅意味著循環結束的迭代,因此再次返回頂部(即`loop do`)。
因此,在循環執行中,現在`i`為 2,因此事情不斷進行,直到`i`為`10`,在這種情況下,在`break if i == 10`中,`i == 10`變為`true`并中斷了循環。
**練習**:嘗試修改 [break_at_10.rb](code/break_at_10.rb) ,當我們完成打印 10 時,程序必須打印“媽媽我已經完成打印 10”。
**答案:** [telling_mom.rb](code/telling_mom.rb)
**練習:**這些西方人不喜歡 13,所以編寫了一個程序以從 1 10 20 開始打印,但是省略了 13。答案: [no_13.rb](code/no_13.rb)
**練習:**請說明 [no_13_a.rb](code/no_13_a.rb) 是否有效。 如果是,怎么辦? 如果否,為什么不呢? <sup class="footnote">[ [22](#_footnotedef_22 "View footnote.") ]</sup>
- 前言
- 紅寶石
- 先決條件
- 1.安裝 Ruby
- 2.在線資源
- 3.入門
- 4.比較與邏輯
- 5.循環
- 6.數組
- 7.哈希和符號
- 8.范圍
- 9.功能
- 10.可變范圍
- 11.類&對象
- 12.安全導航
- 13.打破大型程序
- 14.結構和 OpenStruct
- 15. Rdoc
- 16. Ruby 樣式指南
- 17.模塊和混入
- 18.日期和時間
- 19.文件
- 20. Proc,Lambda 和塊
- 21.多線程
- 22.異常處理
- 23.正則表達式
- 24.寶石
- 25.元編程
- 26.基準
- 27.測試驅動開發
- 28.觀察者模式
- 29.模板模式
- 30.工廠模式
- 31.裝飾圖案
- 32.適配器模式
- 33.單例模式
- 34.復合模式
- 35.建造者模式
- 36.策略模式
- 贊助商
- 捐
- 人們怎么說
- 版權
- 取得這本書