Rust 提供了多种循环控制结构,包括 loop、while、for 以及相关的控制语句。这些结构在 Rust 中都是表达式,可以返回值。
1. loop 循环
基本语法
loop 创建一个无限循环,必须显式使用 break 退出。
rust
fn main() {
let mut counter = 0;
loop {
println!("循环次数: {}", counter);
counter += 1;
if counter >= 5 {
break; // 退出循环
}
}
}
loop 返回值
loop 是表达式,可以通过 break 返回值。
rust
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // 返回 20
}
};
println!("结果是: {}", result); // 输出: 20
}
嵌套循环和标签
rust
fn main() {
let mut count = 0;
'outer: loop {
println!("进入外层循环,count = {}", count);
let mut inner = 0;
'inner: loop {
println!(" 内层循环,inner = {}", inner);
inner += 1;
if inner >= 3 {
break 'inner; // 跳出内层循环
}
}
count += 1;
if count >= 2 {
break 'outer; // 跳出外层循环
}
}
println!("循环结束");
}
2. while 循环
基本语法
while 在条件为真时执行循环。
rust
fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("发射!");
}
while let 模式匹配
while let 在模式匹配成功时继续循环。
rust
fn main() {
let mut stack = Vec::new();
// 压入数据
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
// 弹出数据直到栈为空
while let Some(top) = stack.pop() {
println!("弹出: {}", top);
}
println!("栈已空");
// 另一个例子:处理Option
let mut values = vec![Some(1), Some(2), None, Some(3)];
while let Some(Some(value)) = values.pop() {
println!("处理值: {}", value);
}
}
复杂条件的 while
rust
fn main() {
let mut x = 0;
let mut y = 10;
// 复合条件
while x < 5 && y > 5 {
println!("x = {}, y = {}", x, y);
x += 1;
y -= 1;
}
// 使用函数作为条件
fn should_continue(count: i32) -> bool {
count < 10
}
let mut count = 0;
while should_continue(count) {
println!("计数: {}", count);
count += 1;
}
}
3. for 循环
遍历集合
Rust 的 for 循环主要用于遍历迭代器。
rust
fn main() {
// 遍历数组
let arr = [10, 20, 30, 40, 50];
for element in arr.iter() {
println!("元素: {}", element);
}
// 简化写法(数组会隐式转换为迭代器)
for element in arr {
println!("简化写法: {}", element);
}
// 遍历切片
let slice = &arr[1..4]; // [20, 30, 40]
for element in slice {
println!("切片元素: {}", element);
}
}
范围迭代
使用范围表达式进行迭代。
rust
fn main() {
// 正向范围 (包含)
for number in 1..=5 { // 1, 2, 3, 4, 5
println!("正向: {}", number);
}
// 正向范围 (不包含)
for number in 1..5 { // 1, 2, 3, 4
println!("正向不包含: {}", number);
}
// 反向迭代
for number in (1..5).rev() { // 4, 3, 2, 1
println!("反向: {}", number);
}
// 步长迭代
for number in (0..10).step_by(2) { // 0, 2, 4, 6, 8
println!("步长2: {}", number);
}
}
遍历向量
rust
fn main() {
let v = vec![10, 20, 30];
// 获取值(所有权)
for value in v {
println!("值: {}", value);
}
// 注意:这里 v 的所有权已被移动
let v2 = vec![40, 50, 60];
// 获取引用(不获取所有权)
for value in &v2 {
println!("引用值: {}", value);
}
// v2 仍然可用
println!("向量长度: {}", v2.len());
// 获取可变引用
let mut v3 = vec![1, 2, 3];
for value in &mut v3 {
*value *= 2; // 修改值
}
println!("修改后: {:?}", v3); // [2, 4, 6]
}
遍历 HashMap
rust
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert("Alice", 90);
scores.insert("Bob", 85);
scores.insert("Charlie", 95);
// 遍历键值对
for (name, score) in &scores {
println!("{}: {}", name, score);
}
// 只遍历键
for name in scores.keys() {
println!("学生: {}", name);
}
// 只遍历值
for score in scores.values() {
println!("分数: {}", score);
}
// 遍历并修改值
let mut mutable_scores = HashMap::new();
mutable_scores.insert("Alice", 90);
for score in mutable_scores.values_mut() {
*score += 5;
}
println!("加分后: {:?}", mutable_scores);
}
4. 循环控制语句
break 和 continue
rust
fn main() {
// break 示例
let mut count = 0;
loop {
count += 1;
if count == 3 {
println!("遇到 3,跳过");
continue; // 跳过本次循环剩余部分
}
if count == 5 {
println!("遇到 5,终止循环");
break; // 终止循环
}
println!("当前计数: {}", count);
}
// 带值的 break
let result = loop {
for i in 1..10 {
if i * i > 50 {
break i; // 跳出内层循环,返回 i
}
}
break 0; // 跳出外层循环,返回 0
};
println!("结果: {}", result);
}
break 返回值的作用域
rust
fn main() {
let result = 'outer: loop {
let inner_result = loop {
break 'outer 42; // 直接跳出外层循环并返回值
};
// 这里的代码不会执行
break inner_result * 2;
};
println!("结果是: {}", result); // 42
}
5. 迭代器方法
Rust 的迭代器提供了丰富的链式方法。
基本迭代器方法
rust
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
// map: 转换每个元素
let doubled: Vec<i32> = numbers.iter()
.map(|x| x * 2)
.collect();
println!("翻倍后: {:?}", doubled); // [2, 4, 6, 8, 10]
// filter: 过滤元素
let evens: Vec<&i32> = numbers.iter()
.filter(|&x| x % 2 == 0)
.collect();
println!("偶数: {:?}", evens); // [2, 4]
// fold: 累积计算
let sum = numbers.iter()
.fold(0, |acc, x| acc + x);
println!("总和: {}", sum); // 15
// enumerate: 获取索引和值
for (index, value) in numbers.iter().enumerate() {
println!("索引 {}: 值 {}", index, value);
}
}
链式迭代器操作
rust
fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let result: Vec<i32> = numbers.iter()
.filter(|&x| x % 2 == 0) // 只保留偶数
.map(|x| x * 3) // 乘以3
.take(3) // 只取前3个
.collect();
println!("结果: {:?}", result); // [6, 12, 18]
// 复杂的链式操作
let complex_result: i32 = numbers.iter()
.skip(2) // 跳过前2个
.take(5) // 取5个
.filter(|&x| x > &3) // 大于3
.map(|x| x * 2) // 乘以2
.sum(); // 求和
println!("复杂操作结果: {}", complex_result);
}
6. 循环表达式返回值
Rust 中所有循环结构都可以返回值。
各种循环的返回值
rust
fn main() {
// loop 返回值
let loop_result = {
let mut i = 0;
loop {
i += 1;
if i >= 5 {
break i * 10;
}
}
};
println!("loop 结果: {}", loop_result); // 50
// while 返回值(通过块表达式)
let while_result = {
let mut i = 0;
let mut sum = 0;
while i < 5 {
sum += i;
i += 1;
}
sum // 块表达式的返回值
};
println!("while 结果: {}", while_result); // 10
// for 循环返回值
let for_result = {
let mut sum = 0;
for i in 1..=5 {
sum += i;
}
sum
};
println!("for 结果: {}", for_result); // 15
}
7. 性能考虑
迭代器 vs 索引循环
rust
fn main() {
let vec = vec![1, 2, 3, 4, 5];
// 推荐:使用迭代器(更安全,通常性能更好)
let sum1: i32 = vec.iter().sum();
// 不推荐:使用索引(容易越界)
let mut sum2 = 0;
for i in 0..vec.len() {
sum2 += vec[i];
}
println!("sum1 = {}, sum2 = {}", sum1, sum2);
// 需要索引时的推荐写法
for (i, value) in vec.iter().enumerate() {
println!("索引 {}: 值 {}", i, value);
}
}
避免不必要的 collect()
rust
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
// 不好:创建了中间集合
let doubled: Vec<i32> = numbers.iter()
.map(|x| x * 2)
.collect();
for num in &doubled {
println!("{}", num);
}
// 更好:直接使用迭代器
for num in numbers.iter().map(|x| x * 2) {
println!("{}", num);
}
// 计算而不收集
let sum_of_squares: i32 = numbers.iter()
.map(|x| x * x)
.sum();
println!("平方和: {}", sum_of_squares);
}
8. 实际应用示例
示例1:查找元素
rust
fn find_first_even(numbers: &[i32]) -> Option<i32> {
for &num in numbers {
if num % 2 == 0 {
return Some(num);
}
}
None
}
fn main() {
let nums = vec![1, 3, 5, 4, 7];
match find_first_even(&nums) {
Some(even) => println!("找到第一个偶数: {}", even),
None => println!("没有找到偶数"),
}
}
示例2:矩阵处理
rust
fn process_matrix(matrix: &[Vec<i32>]) -> Vec<i32> {
let mut result = Vec::new();
for row in matrix {
let row_sum: i32 = row.iter().sum();
result.push(row_sum);
// 处理每行元素
for &value in row {
if value > 10 {
println!("发现大值: {}", value);
}
}
}
result
}
fn main() {
let matrix = vec![
vec![1, 2, 3],
vec![4, 5, 6],
vec![7, 8, 9],
];
let sums = process_matrix(&matrix);
println!("每行和: {:?}", sums); // [6, 15, 24]
}
示例3:游戏循环
rust
struct Game {
score: u32,
lives: u8,
level: u8,
}
impl Game {
fn new() -> Self {
Game {
score: 0,
lives: 3,
level: 1,
}
}
fn play(&mut self) -> u32 {
println!("游戏开始!");
'game_loop: loop {
println!("=== 第 {} 关,生命: {},分数: {} ===",
self.level, self.lives, self.score);
// 关卡逻辑
for enemy in 1..=5 {
println!("遇到敌人 {}", enemy);
// 模拟战斗
if self.lives == 0 {
println!("游戏结束!");
break 'game_loop;
}
if rand::random() { // 50% 几率获胜
self.score += 100;
println!("击败敌人! +100 分");
} else {
self.lives -= 1;
println!("被攻击! 剩余生命: {}", self.lives);
}
}
// 过关
self.level += 1;
self.score += 500; // 过关奖励
if self.level > 3 {
println!("通关!");
break 'game_loop;
}
}
self.score
}
}
fn main() {
let mut game = Game::new();
let final_score = game.play();
println!("最终分数: {}", final_score);
}
示例4:数据处理流水线
rust
fn process_data_stream(data: Vec<Option<i32>>) -> Vec<i32> {
let mut results = Vec::new();
// 使用 while let 处理流式数据
let mut stream = data.into_iter();
while let Some(maybe_value) = stream.next() {
if let Some(value) = maybe_value {
// 处理有效数据
if value > 0 {
let processed = value * 2;
results.push(processed);
// 处理一定数量后提前退出
if results.len() >= 10 {
break;
}
}
}
}
results
}
fn main() {
let data = vec![
Some(1), Some(-2), None, Some(3), Some(4),
Some(5), None, Some(6), Some(7), Some(8),
Some(9), Some(10), Some(11), Some(12),
];
let processed = process_data_stream(data);
println!("处理结果: {:?}", processed);
}
9. 最佳实践总结
- 优先使用迭代器:更安全,表达力更强
- 避免索引循环:除非确实需要索引且性能要求高
- 合理使用循环标签:处理复杂嵌套循环
- 利用循环返回值:简化代码逻辑
- 注意所有权:在循环中使用引用避免移动
- 使用合适的循环结构 :
- 已知迭代次数:使用
for - 条件循环:使用
while - 无限循环:使用
loop - 模式匹配循环:使用
while let
- 已知迭代次数:使用
Rust 的循环系统结合了安全性、表达力和性能,是 Rust 编程中的重要组成部分。