
循环是编程中重复执行代码块的基本构造。Rust提供了三种主要的循环类型:
Rust的循环还有一个独特特性:循环也可以返回值!这使得循环在Rust中也是表达式,可以与其他表达式组合使用。
本文将全面介绍Rust的循环系统,包括:
通过本文的学习,你将能够:
loop 关键字创建了一个无限循环,必须使用 break 才能退出:
fn main() {
loop {
println!("无限循环!按Ctrl+C退出");
// 在真实程序中,你需要某种条件来break
}
}fn main() {
let mut counter = 0;
loop {
println!("计数: {}", counter);
counter += 1;
if counter >= 5 {
break; // 退出循环
}
}
println!("循环结束");
}
这是Rust循环最独特的特性:loop 可以返回值!
fn main() {
let mut counter = 0;
// loop表达式返回break语句的值
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // 返回 20
}
};
println!("结果: {}", result); // 20
}
关键规则:
break 后面可以跟一个值,这个值会成为loop表达式的返回值break 的值类型必须相同()fn main() {
// 示例1:查找第一个满足条件的数
let result = loop {
static mut COUNTER: u32 = 0;
unsafe {
COUNTER += 1;
if COUNTER > 100 {
break None; // 没找到
}
if COUNTER % 7 == 0 && COUNTER % 13 == 0 {
break Some(COUNTER); // 找到了
}
}
};
match result {
Some(n) => println!("找到的数字: {}", n),
None => println!("未找到"),
}
// 示例2:重试机制
let mut attempts = 0;
let success = loop {
attempts += 1;
println!("尝试 {}...", attempts);
// 模拟操作(实际中可能是网络请求等)
if attempts >= 3 {
break false; // 失败
}
if attempts == 2 {
break true; // 成功
}
};
if success {
println!("操作成功!");
} else {
println!("操作失败!");
}
}
while 循环在条件为 true 时持续执行:
fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("发射!");
}
条件必须是 bool 类型:
fn main() {
let mut counter = 0;
// 正确:使用bool条件
while counter < 5 {
println!("计数: {}", counter);
counter += 1;
}
// 错误:不能使用数字作为条件
// while counter {
// ...
// }
let mut option = Some(0);
// 使用Option的判断
while let Some(i) = option {
if i > 2 {
option = None;
} else {
println!("数字: {}", i);
option = Some(i + 1);
}
}
}
fn main() {
// 示例1:数组遍历
let arr = [10, 20, 30, 40, 50];
let mut index = 0;
while index < arr.len() {
println!("arr[{}] = {}", index, arr[index]);
index += 1;
}
// 示例2:条件驱动的循环
let mut guess = 50;
let secret_number = 42;
while guess != secret_number {
if guess > secret_number {
println!("太大了!");
guess -= 1;
} else {
println!("太小了!");
guess += 1;
}
}
println!("猜对了!数字是 {}", secret_number);
}
for 循环是Rust中最常用的循环,通常用于遍历集合或范围:
fn main() {
// 遍历范围(不包含5)
for i in 1..5 {
println!("{}", i); // 1, 2, 3, 4
}
// 遍历范围(包含5)
for i in 1..=5 {
println!("{}", i); // 1, 2, 3, 4, 5
}
// 反向遍历
for i in (1..=5).rev() {
println!("{}", i); // 5, 4, 3, 2, 1
}
}
fn main() {
let arr = [10, 20, 30, 40, 50];
// 遍历数组元素
for element in arr.iter() {
println!("元素: {}", element);
}
// 或者使用引用(更常用)
for element in &arr {
println!("元素: {}", element);
}
// 获取索引和值
for (index, value) in arr.iter().enumerate() {
println!("索引 {}: 值 {}", index, value);
}
// 可变遍历
let mut numbers = [1, 2, 3, 4, 5];
for num in numbers.iter_mut() {
*num *= 2;
}
println!("修改后: {:?}", numbers); // [2, 4, 6, 8, 10]
}
fn main() {
let vec = vec![1, 2, 3, 4, 5];
// 遍历向量
for value in &vec {
println!("值: {}", value);
}
// 获取所有权(会消耗向量)
let vec = vec![10, 20, 30];
for value in vec {
println!("值: {}", value);
}
// vec 在这里已经被消耗,不能再使用
// 遍历并修改
let mut vec = vec![1, 2, 3, 4, 5];
for num in vec.iter_mut() {
*num *= 2;
}
println!("{:?}", vec); // [2, 4, 6, 8, 10]
}
fn main() {
let s = "Hello";
// 遍历字符
for ch in s.chars() {
println!("字符: {}", ch);
}
// 遍历字节
for byte in s.bytes() {
println!("字节: {}", byte);
}
// 遍历字符及其索引
for (i, ch) in s.char_indices() {
println!("位置 {}: 字符 {}", i, ch);
}
}
fn main() {
// 使用迭代器方法
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 过滤和映射
for num in numbers.iter()
.filter(|&&x| x % 2 == 0)
.map(|&x| x * 2) {
println!("偶数翻倍: {}", num);
}
// 跳过和限制
for i in (1..=100).skip(10).take(5) {
println!("{}", i); // 11, 12, 13, 14, 15
}
// 步长
for i in (0..10).step_by(2) {
println!("{}", i); // 0, 2, 4, 6, 8
}
}
break 用于立即退出循环:
fn main() {
let mut counter = 0;
loop {
counter += 1;
if counter == 5 {
break; // 退出循环
}
println!("计数: {}", counter);
}
println!("循环在第 {} 次迭代时退出", counter);
}continue 用于跳过当前迭代,继续下一次迭代:
fn main() {
for i in 1..=10 {
if i % 2 == 0 {
continue; // 跳过偶数
}
println!("奇数: {}", i); // 只打印 1, 3, 5, 7, 9
}
}fn main() {
let mut number = 0;
while number < 10 {
number += 1;
if number == 3 {
continue; // 跳过3
}
if number == 8 {
break; // 在8时退出
}
println!("数字: {}", number);
}
// 输出: 1, 2, 4, 5, 6, 7
}fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for num in numbers {
if num == 5 {
continue; // 跳过5
}
if num == 8 {
break; // 在8时退出
}
println!("数字: {}", num);
}
// 输出: 1, 2, 3, 4, 6, 7
}当有嵌套循环时,有时候需要从内层循环退出外层循环,这时就需要循环标签:
fn main() {
// 没有标签的情况
'outer: loop {
println!("外层循环");
'inner: loop {
println!("内层循环");
break 'outer; // 退出外层循环
}
// 这里的代码不会执行
}
println!("退出所有循环");
}fn main() {
let matrix = vec![
vec![1, 2, 3],
vec![4, 5, 6],
vec![7, 8, 9],
];
'search: for (row_idx, row) in matrix.iter().enumerate() {
for (col_idx, &value) in row.iter().enumerate() {
if value == 5 {
println!("找到5在位置 ({}, {})", row_idx, col_idx);
break 'search; // 退出外层循环
}
}
}
}fn main() {
'outer: for i in 1..=3 {
'inner: for j in 1..=3 {
if j == 2 {
continue 'outer; // 继续外层循环的下一次迭代
}
println!("i={}, j={}", i, j);
}
}
// 输出:
// i=1, j=1
// i=2, j=1
// i=3, j=1
}fn main() {
// 打印九九乘法表
for i in 1..=9 {
for j in 1..=i {
print!("{}×{}={}\t", j, i, i * j);
}
println!();
}
}fn main() {
// while嵌套for
let mut outer = 0;
while outer < 3 {
for i in 1..=3 {
println!("外层: {}, 内层: {}", outer, i);
}
outer += 1;
}
// loop嵌套while
let mut counter = 0;
loop {
let mut inner = 0;
while inner < 2 {
println!("外层计数: {}, 内层: {}", counter, inner);
inner += 1;
}
counter += 1;
if counter >= 3 {
break;
}
}
}Rust的迭代器提供了函数式编程风格,有时比循环更清晰:
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
// 使用for循环
let mut sum = 0;
for num in &numbers {
sum += num;
}
println!("循环求和: {}", sum);
// 使用迭代器(更函数式)
let sum: i32 = numbers.iter().sum();
println!("迭代器求和: {}", sum);
// 更多迭代器方法
let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
println!("翻倍: {:?}", doubled);
let evens: Vec<i32> = numbers.iter()
.filter(|&x| x % 2 == 0)
.copied()
.collect();
println!("偶数: {:?}", evens);
}场景 | 推荐 | 原因 |
|---|---|---|
简单遍历 | for循环 | 更直观 |
数据转换 | 迭代器 | 更函数式,可链式调用 |
条件查找 | 迭代器(find) | 更简洁 |
副作用操作 | 循环 | 需要执行副作用 |
复杂控制流 | 循环 | 需要break/continue |
fn main() {
let arr = [10, 20, 30, 40, 50];
let target = 30;
// 使用for循环查找
let mut found = false;
let mut index = None;
for (i, &value) in arr.iter().enumerate() {
if value == target {
found = true;
index = Some(i);
break;
}
}
match index {
Some(i) => println!("找到 {} 在索引 {}", target, i),
None => println!("未找到 {}", target),
}
// 使用迭代器(更简洁)
if let Some(i) = arr.iter().position(|&x| x == target) {
println!("找到 {} 在索引 {}", target, i);
}
}fn main() {
let n = 10;
let mut fib = vec![0, 1];
// 使用for循环生成
for i in 2..n {
let next = fib[i - 1] + fib[i - 2];
fib.push(next);
}
println!("斐波那契数列: {:?}", fib);
// 使用loop生成(另一种方式)
let mut a = 0;
let mut b = 1;
let mut count = 0;
loop {
if count >= n {
break;
}
print!("{} ", a);
let next = a + b;
a = b;
b = next;
count += 1;
}
println!();
}fn main() {
let secret_number = 42;
let mut attempts = 0;
let max_attempts = 5;
loop {
attempts += 1;
if attempts > max_attempts {
println!("游戏结束!答案是 {}", secret_number);
break;
}
// 模拟用户猜测(实际中需要从输入读取)
let guess = attempts * 10; // 模拟:10, 20, 30, 40, 50
println!("尝试 {}: 猜测 {}", attempts, guess);
if guess == secret_number {
println!("恭喜!你在 {} 次尝试后猜对了!", attempts);
break;
} else if guess < secret_number {
println!("太小了!");
} else {
println!("太大了!");
}
}
}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 * x) // 平方
.filter(|&x| x > 20) // 过滤大于20的
.collect();
println!("处理结果: {:?}", result);
// 使用for循环实现相同功能
let mut result2 = Vec::new();
for num in numbers {
if num % 2 == 0 {
let squared = num * num;
if squared > 20 {
result2.push(squared);
}
}
}
println!("循环结果: {:?}", result2);
}fn main() {
// 问题:没有退出条件
// let mut x = 0;
// loop {
// x += 1;
// println!("{}", x);
// }
// 解决方案:添加退出条件
let mut x = 0;
loop {
x += 1;
if x > 10 {
break;
}
println!("{}", x);
}
}fn main() {
// 错误:break返回值的类型不一致
// let result = loop {
// if true {
// break 5; // i32
// } else {
// break "five"; // &str - 类型不匹配!
// }
// };
// 解决方案:返回相同类型
let result = loop {
if true {
break Some(5);
} else {
break None;
}
};
}fn main() {
let mut counter = 0;
// 这个loop返回 ()
let result = loop {
counter += 1;
if counter >= 5 {
break; // 没有返回值
}
};
println!("结果: {:?}", result); // ()
// 如果需要返回值
let result2 = loop {
counter += 1;
if counter >= 5 {
break counter * 2; // 返回 10
}
};
println!("结果: {}", result2); // 10
}fn main() {
let mut numbers = vec![1, 2, 3, 4, 5];
// 错误:不能在迭代时修改
// for num in numbers.iter() {
// *num *= 2; // 编译错误!iter() 返回不可变引用
// }
// 解决方案1:使用iter_mut()
for num in numbers.iter_mut() {
*num *= 2;
}
println!("修改后: {:?}", numbers);
// 解决方案2:使用索引
let mut numbers2 = vec![1, 2, 3, 4, 5];
for i in 0..numbers2.len() {
numbers2[i] *= 2;
}
println!("修改后: {:?}", numbers2);
}fn main() {
let numbers: Vec<i32> = (1..=1_000_000).collect();
// 方式1:for循环
let start = std::time::Instant::now();
let mut sum1 = 0;
for num in &numbers {
sum1 += num;
}
let duration1 = start.elapsed();
println!("for循环耗时: {:?}", duration1);
// 方式2:迭代器
let start = std::time::Instant::now();
let sum2: i32 = numbers.iter().sum();
let duration2 = start.elapsed();
println!("迭代器耗时: {:?}", duration2);
// 注意:在发布模式下,两者性能通常相同(零成本抽象)
}fn main() {
let numbers = vec![1, 2, 3, 4, 5];
// 不推荐:每次都创建新的向量
// let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
// 如果不需要分配,直接使用迭代器
for doubled in numbers.iter().map(|x| x * 2) {
println!("{}", doubled);
}
}使用不同的循环方式计算1到100的和(for循环、while循环、loop循环)。
使用循环找出1到100之间的所有素数。
使用循环和迭代器两种方式反转一个字符串。
使用嵌套循环打印各种图案(三角形、菱形等)。
编写程序计算一组数字的平均值,使用迭代器和循环两种方式。
编写一个loop循环,根据条件返回不同的值。
场景 | 推荐 | 原因 |
|---|---|---|
需要无限循环直到条件满足 | loop | 明确的退出点 |
基于条件的重复 | while | 简洁的条件判断 |
遍历集合或范围 | for | 最常用,最安全 |
需要返回值 | loop | 可以返回break的值 |
函数式处理 | 迭代器 | 链式调用,可读性强 |
掌握了循环后,下一步我们将学习: