Rust基础学习(三)——控制流

paw5zx Lv4

控制流(Control Flow)

控制流(Control Flow)指的是程序执行代码的顺序控制机制,它允许开发者根据条件或循环逻辑决定代码的执行路径。Rust的控制流与其他编程语言类似,但具有更严格的类型安全和表达式特性。最常见控制流结构是if表达式和循环。

if表达式

if表达式允许你根据条件来分支代码,与if表达式中条件关联的代码块一般被称为分支(arm)

1
2
3
4
5
6
7
8
9
// 若condition的值为true,则执行A代码,否则执行B代码
if condition == true
{
// A...
}
else
{
// B...
}

再看下述代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
fn main()
{
let condition = true;
let number = if condition
{
5
}
else
{
6
};

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

注意:

  • if语句块是表达式,这里我们使用if表达式的返回值来给number进行赋值
  • 使用if表达式赋值时,通常要求所有分支返回的类型一致,否则会编译错误(特例:分支返回发散类型时,即使与其他分支返回类型不同,也可以通过编译)
  • if的条件必须是bool类型,否则会编译报错
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 此段代码编译失败
    fn main()
    {
    let number = 3;

    if number
    {
    println!("number was three");
    }
    }

使用else if处理多重条件

可以通过将else ififelse结合来处理多重条件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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整除,但我们没有看到输出number is divisible by 2,这是因为Rust只会执行第一个条件为真的代码块,一旦找到这样的条件,它便不会再检查其余的条件。

使用大量的else if表达式会使代码变得非常丑陋。后面将介绍一种强大的Rust分支结构match,专门用来解决多分支模式匹配的问题。

循环(Loop)

Rust有三种循环:loopwhilefor

重复循环loop

loop关键字告诉Rust无限重复执行某段代码,直到你明确告诉它停止。

1
2
3
4
5
6
7
8
// 不建议运行此段代码
fn main()
{
loop
{
println!("again!");
}
}

当运行上述代码时,会看到again!被不停地打印,直到我们手动停止程序。大多数终端支持键盘快捷键ctrl-c来中断程序。

Rust还提供了一种通过代码跳出循环的方式。你可以在循环中使用break关键字来告诉程序何时停止执行循环,并将结果传递到循环外部(loop是一个表达式,因此可以返回一个值)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn main()
{
let mut counter = 0;

let result = loop
{
counter += 1;

if counter == 10
{
break counter * 2;
}
};

println!("The result is {}", result);
}

注意:

  • break可以单独使用,也可以后面跟一个返回值
  • break跳出当前循环,而return是直接退出当前函数

循环标签(Loop Label)

循环标签用于消除多层循环间的歧义,如果在循环中嵌套了其他循环,breakcontinue默认作用于最内层的循环。你可以选择为循环指定一个循环标签,然后与breakcontinue一起使用,这样可以让这些关键字作用于具有特定标签的循环,而不是最内层的循环。循环标签必须以单引号开头。以下是一个包含两层嵌套循环的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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}");
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cargo run
Compiling loops v0.1.0 (file:///projects/loops)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.58s
Running `target/debug/loops》
count = 0
remaining = 10
remaining = 9
count = 1
remaining = 10
remaining = 9
count = 2
remaining = 10
End count = 2

条件循环while

while关键字会评估某个条件,当条件为真时,循环继续运行;当条件不再为真时,跳出循环。

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

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

number -= 1;
}

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

其实等价于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main()
{
let mut number = 3;

loop
{
if number == 0
{
break;
}

println!("{number}!");

number -= 1;
}

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

只不过使用while要简洁的多

while结构也可以用来遍历集合(例如数组)中的元素:

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

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

index += 1;
}
}

在这段代码中,程序按数组元素计数。它从索引0开始,然后循环直到达到数组的最后一个索引(即当index < 5不再为真时)。运行这段代码将打印数组中的每个元素:

1
2
3
4
5
6
7
8
9
$ cargo run
Compiling loops v0.1.0 (file:///projects/loops)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/loops》
the value is: 10
the value is: 20
the value is: 30
the value is: 40
the value is: 50

然而,这种方法容易出错:如果索引值或测试条件不正确,我们可能会导致程序崩溃。例如,如果你将数组a的定义更改为只有四个元素,但忘记将条件更新为while index < 4,代码将会崩溃。此外,这种方法速度较慢,因为编译器在每次循环迭代时都会添加运行时代码来检查索引是否在数组的边界内。

对于上述情况,有一种更简洁的替代方案:for循环

遍历循环for

for关键字用来遍历集合中的每个元素并执行一些代码。

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

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

相较于while的形式,for循环消除了由于超出数组范围或未遍历到足够远而遗漏某些项而导致错误的可能性,更佳的安全和简洁。

以下是使用for循环和rev方法(尚未讨论)来实现倒计时的代码:

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

参考文章

1.《Rust语言圣经》
2.《The Rust Programming Language》

  • 标题: Rust基础学习(三)——控制流
  • 作者: paw5zx
  • 创建于 : 2025-02-09 09:48:10
  • 更新于 : 2025-02-09 17:29:09
  • 链接: https://paw5zx.github.io/rust-common-concepts-3/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论