if,循环
根据条件是否为真来决定是否执行某些代码,以及根据条件是否为真来重复运行一段代码的能力是大部分编程语言的基本组成部分。Rust
代码中最常见的用来控制执行流的结构是 if
表达式和循环。
if
表达式允许根据条件执行不同的代码分支。你提供一个条件并表示 “如果条件满足,运行这段代码;如果条件不满足,不运行这段代码。”
fn main() {
let number = 3;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}
所有的 if
表达式都以 if
关键字开头,其后跟一个条件。在这个例子中,条件检查变量 number
的值是否小于5
。在条件为 true
时希望执行的代码块位于紧跟条件之后的大括号中。if
表达式中与条件关联的代码块有时被叫做 arms
。
也可以包含一个可选的 else
表达式来提供一个在条件为false
时应当执行的代码块,这里我们就这么做了。如果不提供 else
表达式并且条件为 false
时,程序会直接忽略 if
代码块并继续执行下面的代码。
尝试运行代码,应该能看到如下输出:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.61s
Running `target/debug/variables`
condition was true
可以将 else if
表达式与 if
和 else
组合来实现多重条件。例如:
fn main() {
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}
这个程序有四个可能的执行路径。运行后应该能看到如下输出:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/variables`
number is divisible by 3
当执行这个程序时,它按顺序检查每个 if
表达式并执行第一个条件为 true
的代码块。注意即使 6
可以被 2
整除,也不会输出 number is divisible by 2
,更不会输出 else
块中的 number is not divisible by 4, 3, or 2
。原因是 Rus
t 只会执行第一个条件为 true
的代码块,并且一旦它找到一个以后,甚至都不会检查剩下的条件了。
因为 if
是一个表达式,我们可以在 let
语句的右侧使用它,例如:
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is: {number}");
}
将if
表达式的返回值赋给一个变量,number
变量将会绑定到表示 if
表达式结果的值上。运行这段代码看看会出现什么:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/variables`
The value of number is: 5
代码块的值是其最后一个表达式的值,而数字本身就是一个表达式。在这个例子中,整个 if
表达式的值取决于哪个代码块被执行。这意味着 if
的每个分支的可能的返回值都必须是相同类型;在上面示例中,if
分支和 else
分支的结果都是 i32
整型。如果它们的类型不匹配,如下面这个例子,则会出现一个错误:
fn main() {
let condition = true;
let number = if condition { 5 } else { "six" };
println!("The value of number is: {number}");
}
当编译这段代码时,会得到一个错误。if
和 else
分支的值类型是不相容的,同时 Rust
也准确地指出在程序中的何处发现的这个问题:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:4:44
|
4 | let number = if condition { 5 } else { "six" };
| - ^^^^^ expected integer, found `&str`
| |
| expected because of this
For more information about this error, try `rustc --explain E0308`.
error: could not compile `variables` due to previous error
if
代码块中的表达式返回一个整数,而 else
代码块中的表达式返回一个字符串。这不可行,因为变量必须只有一个类型。
多次执行同一段代码是很常用的,一个循环执行循环体中的代码直到结尾并紧接着回到开头继续执行,Rust
为此提供了三种循环:loop
、while
和 for
。
loop
关键字告诉 Rust
一遍又一遍地执行一段代码直到你明确要求停止,例子:
fn main() {
loop {
println!("again!");
}
}
当运行这个程序时,我们会看到连续的反复打印 again!
,直到我们手动停止程序。大部分终端都支持一个快捷键,ctrl-c
,来终止一个陷入无限循环的程序。尝试一下:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.33s
Running `target/debug/variables`
again!
again!
again!
again!
again!
again!
again!
^Cagain!
Rust
提供了一种从代码中跳出循环的方法。可以使用 break
关键字来告诉程序何时停止循环。
loop
的一个用例是重试可能会失败的操作,比如检查线程是否完成了任务。然而你可能会需要将操作的结果传递给其它的代码。如果将返回值加入你用来停止循环的 break
表达式,它会被停止的循环返回:
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {result}");
}
在循环之前,我们声明了一个名为counter
的变量并初始化为 0
。接着声明了一个名为 result
来存放循环的返回值。在循环的每一次迭代中,我们将 counter
变量加 1
,接着检查计数是否等于 10
。当相等时,使用 break
关键字返回值 counter * 2
。循环之后,我们通过分号结束赋值给 result
的语句。最后打印出 result
的值,也就是 20
。
运行这段代码看看结果是多少:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/variables`
The result is 20
如果存在嵌套循环,brea
k 和 continue
应用于此时最内层的循环。你可以选择在一个循环上指定一个 循环标签(loop label)
,然后将标签与 break
或 continue
一起使用,使这些关键字应用于已标记的循环而不是最内层的循环。下面是一个包含两个嵌套循环的示例:
fn main() {
let mut count = 0;
'counting_up: loop {
println!("count = {count}");
let mut remaining = 10;
loop {
println!("remaining = {remaining}");
if remaining == 9 {
break; //退出内层循环
}
if count == 2 {
break 'counting_up; //退出外层循环
}
remaining -= 1;
}
count += 1;
}
println!("End count = {count}");
}
外层循环有一个标签 counting_up
,它将从 0
数到 2
。没有标签的内部循环从 10
向下数到 9
。第一个没有指定标签的break
将只退出内层循环。break 'counting_up
; 语句将退出外层循环。这个代码打印:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.35s
Running `target/debug/variables`
count = 0
remaining = 10
remaining = 9
count = 1
remaining = 10
remaining = 9
count = 2
remaining = 10
End count = 2
在程序中计算循环的条件也很常见。当条件为 true
,执行循环。当条件不再为 true
,调用 break
停止循环。这个循环类型可以通过组合 loop
、if
、else
和 break
来实现。
然而,这个模式太常用了,Rust
为此内置了一个语言结构,它被称为 while
循环。示例:
fn main() {
let mut number = 3;
while number != 0 {
println!("{number}");
number -= 1;
}
println!("LIFTOFF!!!");
}
while
:程序循环三次,每次数字都减一。接着,在循环结束后,打印出另一个信息并退出
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.26s
Running `target/debug/variables`
3
2
1
LIFTOFF
这种结构消除了很多使用 loop
、if
、else
和 break
时所必须的嵌套,这样更加清晰。当条件为 true
就执行,否则退出循环。
for
循环是条件循环,即循环运行特定次数。 Rust
语言中for
循环的行为与其他语言略有不同。 执行for
循环直到条件为假。可以使用 for
循环来对一个集合的每个元素执行一些代码:
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}
运行这段代码会打印出数组中的每一个元素:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/variables`
the value is: 10
the value is: 20
the value is: 30
the value is: 40
the value is: 50
for
循环的安全性和简洁性使得它成为 Rust
中使用最多的循环结构。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!