(三)Rust控制流程

本文最后更新于 2024年6月25日 下午

在大多数语言中,在条件满足的情况下执行相应代码或者重复执行代码块是非常基础的。在Rust中可以使用条件表达式和循环来控制代码执行流程。

条件表达式

if表达式根据条件是否满足将代码执行分为两个分支。你可以提供一个条件然后声明,如果条件满足,执行这段代码,如果条件不满足,不执行这段代码。下面是一个例子:

1
2
3
4
5
6
7
8
9
fn main() {
let number = 3;

if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}

所有的if表达式均为关键词if加条件的形式。这个例子中,检查number是否小于5,如果条件满足,程序将会执行if条件表达式后面花括号中的相关代码,否则,如果存在的话,程序将会执行else后面花括号中的相关代码。

需要注意的是,if后跟的条件必须为布尔值,否则程序将会在编译期报错。

使用else if处理多重条件

你可以结合ifelseelse if来进行多重条件判断。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
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");
}
}

当程序执行时,依次检查if的条件,当条件满足时,执行其后面的代码块。注意到即使6能够被2整除,我们却看不到输出,因为在执行6被3整除的代码后,将不再检查后续的条件。

let中使用if

由于if是一个表达式,其返回值可以作为let声明的右值。下面是一个例子:

1
2
3
4
5
6
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };

println!("The value of number is: {number}");
}

从上面例子中可以看出,在程序运行时,number有可能是任意分支的返回值,对于静态类型语言来说,类型必须在编译期确定,因此,任意分支的返回值类型需要相同。上面例子中,条件表达式和number的类型被隐式推导为i32

循环

多次执行代码在程序设计中非常常见。在Rust中,有三种循环loop,while,for,下面我们依次尝试这三种循环。

loop

loop关键字使代码块循环执行,直到显式退出循环,代码块才会终止。下面是一个例子:

1
2
3
4
5
6
fn main() {
loop {
println!("again!");
break;
}
}

上面循环代码只会执行1次,因为循环代码中遇到break便会跳出循环。

loop循环还有一个用法,通过break使loop返回值。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
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用来接收loop的返回值。每次循环对counter变量加1,当counter等于10时,通过break关键词将counter*2返回。最终打印了result的值,在上面例子中,result的值为20。

在多层循环中,可以使用循环标签,指定break跳出的循环。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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_upcount将会从0增加到2。 没有标签的内层循环,remaining值从10减到9。第一个 break 没有指定跳出哪个循环,那么它将仅跳出内层循环。而 break 'counting_up; 将会跳出外层循环。

while

程序经常会需要在循环中判断是否符合运行条件。如果条件成立程序运行,当条件不再成立,程序退出。while实现的行为就像对loopifelsebreak的结合,当条件成立,程序运行,条件不成立,调用break退出循环。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
fn main() {
let mut number = 3;

while number != 0 {
println!("{number}!");

number -= 1;
}

println!("LIFTOFF!!!");
}

更进一步,可以使用while循环对数组中的元素遍历。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;

while index < 5 {
println!("the value is: {}", a[index]);

index += 1;
}
}

for

使用while遍历数组的例子中,维护了一个索引值,根据索引值获取数组中每个元素,当索引范围越界,程序便会出错。在Rust中有一种更为简便的遍历数组的方式,使用for关键字。不同于手动维护索引,使用for循环可以避免运行期越界检查,会更快。下面是一个例子:

1
2
3
4
5
6
7
fn main() {
let a = [10, 20, 30, 40, 50];

for element in a {
println!("the value is: {element}");
}
}

在某些场景可能需要代码运行确定次数,for循环依旧可以实现。实现方法需要使用标准库Range,可以从一个数到另一个数生成一个数字序列。下面是一个例子:

1
2
3
4
5
6
fn main() {
for number in (1..4).rev() {
println!("{number}!");
}
println!("LIFTOFF!!!");
}

其中rev函数用来反转范围。

参考

Rust docs


(三)Rust控制流程
https://www.happyallday.cn/Rust/RustLang_03_ControlFlow/
作者
DevoutPrayer
发布于
2024年6月25日
更新于
2024年6月25日
许可协议