Rust 基礎系列 #7: 在 Rust 中使用循環
在 Rust 系列的 上一篇文章 中,我介紹了如何使用 if
和 else
關鍵字來處理 Rust 程序的控制流。
這是處理程序控制流的一種方法。另一種方法是使用循環。因此,讓我們在本文中看看循環。
Rust 中可用的循環
Rust 編程語言有三種不同的循環,基於你想要實現什麼以及可用的內容:
for
while
loop
我假設你對 for
和 while
已經很熟悉了,但 loop
對你來說可能是個新概念。讓我們先從熟悉的概念開始。
for 循環
for
循環主要用於迭代一種稱為迭代器的東西。
這個迭代器可以從任何東西中創建,從數組、向量(很快就會介紹!)、一系列值,或者任何自定義的東西。這裡的可能性是無限的。
來看看 for
循環的語法。
for 迭代變數 in 迭代器 {
<語句>;
}
其中的 迭代變數
在大多數其他編程語言教程中通常被稱為 i
; )
迭代器
可以是任何東西,只要它能告訴下一個值是什麼,如果有的話。
來通過一個程序來理解這個。
fn main() {
let my_arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
println!("迭代數組");
for element in my_arr {
println!("{}", element);
}
println!("n迭代一個真正的迭代器");
for element in my_arr.iter() {
println!("{}", element);
}
println!("nPython 風格的範圍");
for element in 0..10 {
println!("{}", element);
}
}
這裡,我聲明了一個數組,它包含從 0 到 9 的 10 個數字。在第 5 行的 for
循環中,我只是將這個數組指定為迭代器,Rust 會自動處理對這個數組的所有元素的迭代。不需要花哨的 my_arr[i]
魔法。
但是,在第 10 行,我調用了 .iter()
函數。這是一個明確的提及,它基於 my_arr
的值來獲取一個迭代器。這個循環和第 5 行的循環之間唯一的區別是,這裡你是通過在數組上調用 .iter()
函數來明確地調用它的。
在這個上下文環境中,在一個數據類型上調用 .iter()
函數不是必須的。因為這是一個數組,是語言本身提供的一種數據類型,Rust 已經知道如何處理它了。但是你 需要 在自定義數據類型中使用它。
最後,在第 15 行,我們有一個循環,它循環遍歷一個範圍。嗯,差不多是這樣。如果你仔細看,這個範圍看起來很像切片 「類型」。Rust 也知道這一點,並且 為 你處理了迭代(哈哈,明白了嗎?)。
LCTT 譯註:此處的梗是,「為你處理了迭代」 的英文原文是 「handles iteration for you",其中的 「for」 與 「for 循環」 的 「for」 是同一個單詞。
輸出如下:
迭代數組
0
1
2
3
4
5
6
7
8
9
迭代一個真正的迭代器
0
1
2
3
4
5
6
7
8
9
Python 風格的範圍
0
1
2
3
4
5
6
7
8
9
while 循環
while
循環可以被認為是非常類似於 if
條件語句。使用 if
語句,只要用戶提供的條件為 true
,if
語句體中的代碼就會被執行 一次。
但是,在 while
循環中,如果條件評估為 true
,循環就會開始循環循環體。只要條件繼續評估為 true
,循環就會繼續迭代。
while
循環只有在循環完成當前迭代中所有語句的執行並且在檢查條件時,它的結果為 false
時才會停止。
來看看 while
循環的語法...
while 條件 {
<語句>;
}
看到了嗎?和 if
條件語句非常相似!不過沒有 else
塊 ; )
來看一個程序來更好地理解這個。
fn main() {
let mut var = 0;
while var < 3 {
println!("{var}");
var += 1;
}
}
我有一個可變變數 var
,它的初始值為 0。只要可變變數 var
中存儲的值小於 3,while
循環就會執行。
在循環中,var
的值被列印出來,然後它的值被增加 1。
這是上面代碼的輸出:
0
1
2
loop 循環
Rust 有一個無限循環。是的,一個沒有開始條件和停止條件的循環。它只是一直循環,直到永遠。當然,它有觸發器來停止代碼本身的循環執行。
無限循環的語法如下:
loop {
<語句>;
}
? 這些循環主要用於 GUI 軟體,退出是一個 顯式 操作。
在我給你一個例子之前,因為這個循環非常特殊,讓我們先看看如何 退出 它 :p
要停止無限循環的執行,需要在循環內使用 break
關鍵字。
來看一個例子,只有 0 到 3 之間的整數(包括 0 和 3)才會被列印到程序輸出。
fn main() {
let mut var = 0;
loop {
if var > 3 {
break;
}
println!("{}", var);
var += 1;
}
}
看待這個特定的例子的最好方法是將它看作是一個增加了一堆沒有必要的東西的 while
循環 ; )
你有一個可變變數 var
,它的初始值為 0,它被用作迭代器。無限循環從一個 if
條件開始,如果 var
的值大於 3,break
關鍵字就會被執行。後來,就像 while
循環的前一個例子一樣,var
的值被列印到標準輸出,然後它的值被增加 1。
它的輸出如下:
0
1
2
3
標記循環
假設有兩個無限循環,一個嵌套在另一個中。由於某種原因,退出條件在最內層循環中被檢查,但這個退出條件是為了退出最外層循環。
在這種情況下,標記循環可能是有益的。
?
break
和continue
關鍵字並不僅僅用於無限循環。它們可以用於 Rust 語言提供的所有三種循環。
接下來是如何標記循環。
'標記: loop {}
要告訴編譯器一個循環被標記了,從一個單引號字元開始,輸入它的標籤,然後跟著一個冒號。然後,繼續使用你通常定義循環的方式。
當你需要退出某個循環時,只需像這樣指定循環標籤:
break '標記;
來看一個例子來更好地理解這個。
fn main() {
let mut a = 0;
let mut b = 0;
'parent: loop {
a += 1;
loop {
println!("a: {}, b: {}", a, b);
b += 1;
if a + b == 10 {
println!("n{} + {} = 10", a, b);
break 'parent;
}
}
}
}
這裡,我使用兩個可變變數 a
和 b
,它們的初始值都設置為 0。
然後,最外層的循環被標記為 parent
。parent
循環將變數 a
的值增加 1,並有一個內部/子循環。
這個(在第 8 行的)子循環列印變數 a
和 b
的值。在這個循環內部,變數 b
的值增加了 1。退出條件是 a + b == 10
。這意味著只要變數 a
和 b
中存儲的值相加,結果為 10,parent
循環就會被打破。即使第 14 行的 break
條件「屬於」內部循環,它也會打破 parent
循環。
來看看程序的輸出。
a: 1, b: 0
a: 1, b: 1
a: 1, b: 2
a: 1, b: 3
a: 1, b: 4
a: 1, b: 5
a: 1, b: 6
a: 1, b: 7
a: 1, b: 8
1 + 9 = 10
就像從程序輸出中可以看出的那樣,循環在 a
和 b
分別具有值 1 和 9 時停止。
continue 關鍵字
如果你已經在其他編程語言(如 C/C++/Java/Python)中使用過循環,你可能已經知道 continue
關鍵字的用法。
當 break
關鍵字用於完全停止循環執行時,continue
關鍵字用於「跳過」循環執行的 當前迭代 並從下一迭代開始(如果條件允許)。
來看一個例子來理解 continue
關鍵字的工作原理。
fn main() {
for i in 0..10 {
if i % 2 == 0 {
continue;
}
println!("{}", i)
}
}
在上面的代碼中,我有一個 for
循環,它迭代了 0 到 9 之間的整數(包括 0 和 9)。一旦循環開始,我就設置了一個條件檢查,看看這個數字是不是偶數。如果這個數字是偶數,continue
關鍵字就會被執行。
但是如果這個數字是奇數,這個數字就會被列印到程序輸出。
來看看這個程序的輸出。
1
3
5
7
9
正如你所看到的,循環似乎一直在「進行」,儘管 0 到 9 之間顯然有偶數。但是因為我使用了 continue
關鍵字,當遇到這個關鍵字時,循環執行就會停止。
這個循環跳過了它下面的任何東西,並繼續下一次迭代。這就是為什麼偶數沒有被列印出來,但是 0 到 9 之間的所有奇數都被列印到了程序輸出中。
總結
要總結這篇長文,我演示了 3 種不同循環的用法:for
、while
和 loop
。我還討論了兩個關鍵字,它們影響這些循環的控制流:break
和 continue
。
我希望你現在能理解每個循環的適當用例。如果你有任何問題,請告訴我。
(題圖:MJ/25579e09-ae1c-47d3-8266-3bd9a54456c0)
via: https://itsfoss.com/rust-loops/
作者:Pratham Patel 選題:lkxed 譯者:Cubik65536 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive