mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-23 21:20:42 +08:00
339 lines
9.7 KiB
Markdown
339 lines
9.7 KiB
Markdown
[#]: subject: "Rust Basics Series #7: Using Loops in Rust"
|
||
[#]: via: "https://itsfoss.com/rust-loops/"
|
||
[#]: author: "Pratham Patel https://itsfoss.com/author/pratham/"
|
||
[#]: collector: "lkxed"
|
||
[#]: translator: "Cubik65536"
|
||
[#]: reviewer: "wxy"
|
||
[#]: publisher: "wxy"
|
||
[#]: url: "https://linux.cn/article-15908-1.html"
|
||
|
||
Rust 基础系列 #7: 在 Rust 中使用循环
|
||
======
|
||
|
||
![][0]
|
||
|
||
在 Rust 系列的 [上一篇文章][1] 中,我介绍了如何使用 `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][a]
|
||
选题:[lkxed][b]
|
||
译者:[Cubik65536](https://github.com/Cubik65536)
|
||
校对:[wxy](https://github.com/wxy)
|
||
|
||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||
|
||
[a]: https://itsfoss.com/author/pratham/
|
||
[b]: https://github.com/lkxed/
|
||
[1]: https://linux.cn/article-15896-1.html
|
||
[0]: https://img.linux.net.cn/data/attachment/album/202306/15/164034klkjbf3ibapjbbfk.jpg |