====== 第四章 控制流 ======
===== 4.1 if表达式 =====
==== 基础if语法 ====
let number = 6;
if number < 5 {
println!("条件为真");
} else {
println!("条件为假");
}
==== 多条件判断 ====
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整除");
}
==== if作为表达式 ====
Rust的if是一个表达式,可以返回值:
let condition = true;
let number = if condition { 5 } else { 6 };
println!("number的值是:{}", number); // 5
**重要规则**:if分支返回的类型必须相同。
// 错误示例
let number = if condition { 5 } else { "six" }; // 编译错误!
===== 4.2 循环 =====
Rust有三种循环:loop、while和for。
==== loop无限循环 ====
loop {
println!("永远循环!");
// 使用break退出
}
**带返回值的loop:**
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // 返回值
}
};
println!("结果:{}", result); // 20
**loop标签:**
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条件循环 ====
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("发射!");
**用while遍历数组:**
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("值为:{}", a[index]);
index += 1;
}
==== for遍历 ====
**遍历集合:**
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("值为:{}", element);
}
**使用Range:**
// 1到3(不包括4)
for number in 1..4 {
println!("{}!", number);
}
// 1到4(包括4)
for number in 1..=4 {
println!("{}!", number);
}
// 反向
for number in (1..4).rev() {
println!("{}!", number);
}
**带索引的遍历:**
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
println!("{} 在索引 {}", value, index);
}
===== 4.3 match表达式 =====
match是Rust强大的模式匹配结构,类似C的switch但功能更强大。
==== 基础match ====
let number = 7;
match number {
1 => println!("一"),
2 => println!("二"),
3 => println!("三"),
4 => println!("四"),
5 => println!("五"),
_ => println!("其他"),
}
**match必须穷尽(exhaustive):**
let number = 7;
match number {
1 => println!("一"),
// 错误!缺少其他情况的处理
}
==== 匹配多个模式 ====
let number = 1;
match number {
1 | 2 => println!("一或二"),
3..=7 => println!("三到七之间"),
_ => println!("其他"),
}
==== match返回值 ====
let number = 2;
let result = match number {
1 => "一",
2 => "二",
3 => "三",
_ => "其他",
};
println!("结果是:{}", result);
===== 4.4 模式匹配详解 =====
==== 解构元组 ====
let point = (3, 5);
match point {
(0, 0) => println!("原点"),
(x, 0) => println!("x轴上,x = {}", x),
(0, y) => println!("y轴上,y = {}", y),
(x, y) => println!("点 ({}, {})", x, y),
}
==== 解构结构体 ====
struct Point {
x: i32,
y: i32,
}
let p = Point { x: 0, y: 7 };
match p {
Point { x, y: 0 } => println!("在x轴上,x = {}", x),
Point { x: 0, y } => println!("在y轴上,y = {}", y),
Point { x, y } => println!("点 ({}, {})", x, y),
}
**使用..忽略剩余字段:**
struct Point3D {
x: i32,
y: i32,
z: i32,
}
let p = Point3D { x: 1, y: 2, z: 3 };
match p {
Point3D { x, .. } => println!("x是{}", x),
}
==== 解构枚举 ====
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
let msg = Message::ChangeColor(0, 160, 255);
match msg {
Message::Quit => {
println!("Quit");
}
Message::Move { x, y } => {
println!("移动到 x: {}, y: {}", x, y);
}
Message::Write(text) => {
println!("文本消息:{}", text);
}
Message::ChangeColor(r, g, b) => {
println!("改变颜色为 R: {}, G: {}, B: {}", r, g, b);
}
}
==== 使用if let简化 ====
对于只关心一个模式的情况:
let some_value = Some(3);
// match写法
match some_value {
Some(3) => println!("是三"),
_ => (),
}
// if let写法(更简洁)
if let Some(3) = some_value {
println!("是三");
}
**if let带else:**
if let Some(3) = some_value {
println!("是三");
} else {
println!("不是三");
}
==== while let ====
let mut stack = Vec::new();
stack.push(1);
stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
println!("弹出:{}", top);
}
===== 4.5 绑定与守卫 =====
==== @绑定 ====
@运算符允许在测试模式的同时创建变量:
enum Message {
Hello { id: i32 },
}
let msg = Message::Hello { id: 5 };
match msg {
Message::Hello { id: id_variable @ 3..=7 } => {
println!("id在范围内:{}", id_variable);
}
Message::Hello { id: 10..=12 } => {
println!("id在10到12之间,但没有绑定");
}
Message::Hello { id } => {
println!("其他id:{}", id);
}
}
==== 匹配守卫 ====
let num = Some(4);
match num {
Some(x) if x < 5 => println!("小于5:{}", x),
Some(x) => println!("{}", x),
None => (),
}
**多个模式的守卫:**
let x = 4;
let y = false;
match x {
4 | 5 | 6 if y => println!("yes"),
_ => println!("no"),
}
===== 4.6 模式匹配的更多特性 =====
==== 忽略值 ====
**使用_忽略整个值:**
fn foo(_: i32, y: i32) {
println!("y = {}", y);
}
foo(3, 4);
**使用_忽略部分值:**
let mut setting_value = Some(5);
let new_setting_value = Some(10);
match (setting_value, new_setting_value) {
(Some(_), Some(_)) => {
println!("不能覆盖已有值");
}
_ => {
setting_value = new_setting_value;
}
}
**使用以_开头的名称:**
let s = Some(String::from("Hello!"));
if let Some(_s) = s {
println!("找到了字符串");
}
// println!("{:?}", s); // 错误!s已被移动
使用_则不会移动:
if let Some(_) = s {
println!("找到了字符串");
}
println!("{:?}", s); // 正确!
===== 练习题 =====
==== 练习题4.1:猜数字游戏 ====
use std::io;
fn main() {
let secret_number = 42;
loop {
println!("请输入你的猜测:");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("读取失败");
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("请输入数字!");
continue;
}
};
match guess.cmp(&secret_number) {
std::cmp::Ordering::Less => println!("太小了!"),
std::cmp::Ordering::Greater => println!("太大了!"),
std::cmp::Ordering::Equal => {
println!("猜对了!");
break;
}
}
}
}
==== 练习题4.2:FizzBuzz ====
fn main() {
for n in 1..=100 {
match (n % 3, n % 5) {
(0, 0) => println!("FizzBuzz"),
(0, _) => println!("Fizz"),
(_, 0) => println!("Buzz"),
_ => println!("{}", n),
}
}
}
==== 练习题4.3:简单计算器 ====
fn calculate(a: f64, b: f64, op: char) -> Option {
match op {
'+' => Some(a + b),
'-' => Some(a - b),
'*' => Some(a * b),
'/' => if b != 0.0 { Some(a / b) } else { None },
_ => None,
}
}
fn main() {
let a = 10.0;
let b = 3.0;
let op = '*';
match calculate(a, b, op) {
Some(result) => println!("{} {} {} = {}", a, op, b, result),
None => println!("无效操作或除零错误"),
}
}
==== 练习题4.4:数字转中文 ====
fn number_to_chinese(n: u32) -> String {
match n {
0 => "零".to_string(),
1 => "一".to_string(),
2 => "二".to_string(),
3 => "三".to_string(),
4 => "四".to_string(),
5 => "五".to_string(),
6 => "六".to_string(),
7 => "七".to_string(),
8 => "八".to_string(),
9 => "九".to_string(),
10 => "十".to_string(),
_ => n.to_string(),
}
}
fn main() {
for i in 0..=10 {
println!("{} -> {}", i, number_to_chinese(i));
}
}
===== 本章小结 =====
本章学习了Rust的控制流结构:
* **if表达式**:条件判断,可以作为表达式返回值
* **loop**:无限循环,可以返回值,支持标签跳出
* **while**:条件循环
* **for**:遍历集合或Range,最常用
* **match**:强大的模式匹配,必须穷尽所有情况
* **模式匹配**:解构元组、结构体、枚举
* **if let/while let**:简化单模式匹配
* **匹配守卫**:添加额外条件
* **@绑定**:测试模式同时绑定值
控制流是编程的基础,Rust的模式匹配系统特别强大,建议多加练习。