Rust从入门到精通之入门篇:5.控制流
控制流
学习目标
完成本章学习后,你将能够:
- 使用
if
和else if
表达式进行条件判断 - 在
let
语句中使用if
表达式 - 掌握
match
表达式进行模式匹配 - 使用
loop
创建无限循环并从循环返回值 - 应用
while
循环在条件为真时执行代码 - 使用
for
循环遍历集合和范围 - 理解循环标签在嵌套循环中的应用
在本章中,我们将学习 Rust 中的控制流结构,包括条件判断和循环。控制流允许程序根据条件执行不同的代码块,或者重复执行某些代码块,是编程中的基本构建块。
条件语句
if 表达式
Rust 中的 if
表达式允许根据条件执行不同的代码。基本语法如下:
if 条件 {
// 当条件为真时执行的代码
} else {
// 当条件为假时执行的代码
}
一个简单的例子:
fn main() {
let number = 7;
if number < 5 {
println!("条件为真");
} else {
println!("条件为假");
}
}
在 Rust 中,条件必须是 bool
类型。不像一些语言会自动将非布尔值转换为布尔值,Rust 不会进行这种隐式转换:
fn main() {
let number = 3;
if number { // 错误:expected `bool`, found integer
println!("数字是 3");
}
}
正确的写法是显式地进行比较:
fn main() {
let number = 3;
if number != 0 {
println!("数字不是 0");
}
}
else if 表达式
可以使用 else if
处理多个条件:
fn main() {
let number = 6;
if number % 4 == 0 {
println!("数字能被 4 整除");
} else if number % 3 == 0 {
println!("数字能被 3 整除");
} else if number % 2 == 0 {
println!("数字能被 2 整除");
} else {
println!("数字不能被 4、3 或 2 整除");
}
}
在 let 语句中使用 if
因为 if
是一个表达式,所以可以在 let
语句的右侧使用它:
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("number 的值是: {}", number);
}
在这种情况下,if
和 else
分支的值类型必须相同:
fn main() {
let condition = true;
let number = if condition { 5 } else { "six" }; // 错误:类型不匹配
println!("number 的值是: {}", number);
}
match 表达式
match
是 Rust 中强大的模式匹配工具,它允许我们将一个值与一系列模式进行比较,并根据匹配的模式执行相应的代码。
基本语法:
match 值 {
模式1 => 表达式1,
模式2 => 表达式2,
模式3 => 表达式3,
_ => 默认表达式,
}
一个简单的例子:
fn main() {
let dice_roll = 3;
match dice_roll {
1 => println!("掷出了 1"),
2 => println!("掷出了 2"),
3 => println!("掷出了 3"),
4 => println!("掷出了 4"),
5 => println!("掷出了 5"),
6 => println!("掷出了 6"),
_ => println!("无效的骰子值"),
}
}
match
表达式必须是穷尽的,即必须覆盖所有可能的值。使用 _
通配符可以匹配所有未明确列出的值。
绑定值的模式
match
的分支可以绑定匹配模式的部分值:
fn main() {
let some_value = Some(5);
match some_value {
Some(i) => println!("匹配到值: {}", i),
None => println!("没有值"),
}
}
多模式匹配
可以使用 |
语法匹配多个模式:
fn main() {
let x = 1;
match x {
1 | 2 => println!("1 或 2"),
3 => println!("3"),
_ => println!("其他值"),
}
}
范围匹配
可以使用 ..=
匹配一个范围的值:
fn main() {
let x = 5;
match x {
1..=5 => println!("1 到 5 之间"),
_ => println!("其他值"),
}
}
循环
Rust 提供了三种循环:loop
、while
和 for
。
loop 循环
loop
关键字创建一个无限循环,除非明确退出:
fn main() {
loop {
println!("再来一次!");
// 使用 break 退出循环
break;
}
}
可以使用 break
从循环返回值:
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("结果是: {}", result); // 输出:结果是: 20
}
循环标签
当有嵌套循环时,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!("最终 count = {}", count);
}
while 循环
while
循环在条件为真时执行代码块:
fn main() {
let mut number = 3;
while number != 0 {
println!("{}", number);
number -= 1;
}
println!("发射!");
}
for 循环
for
循环用于遍历集合中的元素:
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("值是: {}", element);
}
}
使用 for
循环遍历范围:
fn main() {
for number in 1..4 {
println!("{}", number);
}
// 输出:1 2 3
for number in 1..=4 {
println!("{}", number);
}
// 输出:1 2 3 4
}
示例程序
让我们编写一个程序,展示 Rust 中的各种控制流结构:
fn main() {
// if 表达式
let number = 6;
if number % 4 == 0 {
println!("数字能被 4 整除");
} else if number % 3 == 0 {
println!("数字能被 3 整除");
} else if number % 2 == 0 {
println!("数字能被 2 整除");
} else {
println!("数字不能被 4、3 或 2 整除");
}
// 在 let 语句中使用 if
let condition = true;
let number = if condition { 5 } else { 6 };
println!("number 的值是: {}", number);
// match 表达式
let dice_roll = 3;
match dice_roll {
1 => println!("掷出了 1"),
2 => println!("掷出了 2"),
3 => println!("掷出了 3"),
4 => println!("掷出了 4"),
5 => println!("掷出了 5"),
6 => println!("掷出了 6"),
_ => println!("无效的骰子值"),
}
// Option 枚举的匹配
let some_value = Some(3);
match some_value {
Some(3) => println!("找到了 3!"),
Some(x) => println!("找到了 {}!", x),
None => println!("什么都没找到"),
}
// loop 循环
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("loop 结果是: {}", result);
// while 循环
let mut number = 3;
while number != 0 {
println!("{}", number);
number -= 1;
}
println!("发射!");
// for 循环遍历数组
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("值是: {}", element);
}
// for 循环遍历范围
println!("正向计数:");
for number in 1..4 {
println!("{}", number);
}
println!("反向计数:");
for number in (1..4).rev() {
println!("{}", number);
}
}
练习题
- 编写一个程序,使用
if
表达式判断一个数是否为偶数,并打印相应的消息。
fn main() {
// 练习题1:使用 if 表达式判断一个数是否为偶数
let number = 42;
if number % 2 == 0 {
println!("{} 是偶数", number);
} else {
println!("{} 是奇数", number);
}
// 使用 if 表达式作为值的示例
let message = if number % 2 == 0 {
"是偶数"
} else {
"是奇数"
};
println!("数字 {} {}", number, message);
}
- 使用
match
表达式编写一个简单的计算器程序,根据用户输入的运算符(+、-、*、/)对两个数进行相应的运算。
use std::io;
fn main() {
// 练习题2:使用 match 表达式编写一个简单的计算器程序
println!("简单计算器");
println!("请输入第一个数字:");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("读取输入失败");
let num1: f64 = input.trim().parse().expect("请输入一个有效的数字");
println!("请输入运算符 (+, -, *, /):");
input.clear();
io::stdin().read_line(&mut input).expect("读取输入失败");
let operator = input.trim();
println!("请输入第二个数字:");
input.clear();
io::stdin().read_line(&mut input).expect("读取输入失败");
let num2: f64 = input.trim().parse().expect("请输入一个有效的数字");
// 使用 match 表达式处理不同的运算符
let result = match operator {
"+" => num1 + num2,
"-" => num1 - num2,
"*" => num1 * num2,
"/" => {
if num2 == 0.0 {
println!("错误:除数不能为零");
return;
} else {
num1 / num2
}
},
_ => {
println!("错误:无效的运算符");
return;
}
};
println!("{} {} {} = {}", num1, operator, num2, result);
}
- 使用
loop
循环实现一个程序,不断要求用户输入一个数字,直到用户输入的数字是 10 的倍数为止。
use std::io;
fn main() {
// 练习题3:使用 loop 循环实现一个程序,不断要求用户输入一个数字,直到用户输入的数字是 10 的倍数为止
println!("请输入一个 10 的倍数来退出程序");
loop {
println!("请输入一个数字:");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("读取输入失败");
// 尝试将输入解析为数字
let number: i32 = match input.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("这不是一个有效的数字,请重试");
continue;
}
};
// 检查数字是否为 10 的倍数
if number % 10 == 0 {
println!("输入的数字 {} 是 10 的倍数,程序退出", number);
break;
} else {
println!("输入的数字 {} 不是 10 的倍数,请重试", number);
}
}
}
- 使用
while
循环计算斐波那契数列的前 10 个数。
fn main() {
// 使用 while 循环计算斐波那契数列的前 10 个数
let mut count = 0;
let mut first = 0;
let mut second = 1;
println!("斐波那契数列的前 10 个数:");
// 打印第一个数
println!("{}", first);
count += 1;
// 打印第二个数
println!("{}", second);
count += 1;
// 使用 while 循环计算剩余的数
while count < 10 {
let next = first + second;
println!("{}", next);
// 更新值以计算下一个数
first = second;
second = next;
count += 1;
}
}
- 使用
for
循环打印出 1 到 100 中所有的质数。
fn main() {
// 练习题5:使用 for 循环打印出 1 到 100 中所有的质数
println!("1 到 100 中的质数:");
// 遍历 2 到 100 的所有数字(1 不是质数)
'outer: for num in 2..=100 {
// 检查当前数字是否为质数
// 质数是只能被 1 和自身整除的数
for i in 2..num {
if num % i == 0 {
// 如果能被其他数整除,则不是质数
continue 'outer;
}
}
// 如果循环完成没有找到因子,则是质数
println!("{}", num);
}
}
这些练习题旨在帮助你巩固本章所学的控制流概念。尝试先自己解决,然后再查看示例解决方案。
总结
在本章中,我们学习了:
- 使用
if
和else if
进行条件判断 - 在
let
语句中使用if
表达式 - 使用
match
表达式进行模式匹配 - 使用
loop
创建无限循环 - 使用
while
循环在条件为真时执行代码 - 使用
for
循环遍历集合和范围
控制流是编程的基础,掌握了这些结构,你就能够编写更复杂、更有用的 Rust 程序。在下一章中,我们将学习 Rust 中的函数,它是代码组织和重用的重要工具。