Rust 流程控制学习教程

Rust 作为一门注重安全与效率的语言,提供了与其他主流语言相似但又有细节差异的流程控制语法,主要包括分支控制 (if-else)和循环控制 (loop、while、for)。本教程将基于 Rust 语言圣经(course.rs) 的内容,带您系统掌握 Rust 流程控制的核心用法。

一、分支控制:根据条件"选择道路"

分支控制的核心是"根据条件判断,执行不同代码块",Rust 中最常用的分支结构是 if-else,且不支持 switch(需用 match 替代,后续进阶内容)。

1.1 基础 if-else:满足条件就执行

if 后面必须跟一个布尔值bool),不能像 C/C++ 那样隐式转换(如数字 0 代表 false),这是 Rust 类型安全的体现。

语法格式
rust 复制代码
if 条件表达式(结果为 bool) {
    // 条件为 true 时执行的代码块
} else if 另一个条件表达式(结果为 bool) {
    // 上一个条件为 false,当前条件为 true 时执行
} else {
    // 所有条件都为 false 时执行(可选)
}
示例:判断数字大小
rust 复制代码
fn main() {
    let score = 85;

    if score >= 90 {
        println!("成绩优秀");
    } else if score >= 70 {
        println!("成绩良好");
    } else if score >= 60 {
        println!("成绩及格");
    } else {
        println!("成绩不及格");
    }
}
// 输出:成绩良好
关键注意点
  • 条件必须是 bool 类型 :若写 if score { ... } 会编译报错,因为 scorei32 类型,无法直接作为条件。
  • 代码块必须用大括号 :即使代码块只有一行,也不能省略 {}(如 if true println!("ok") 是错误的),这是 Rust 强制的代码风格,避免歧义。

1.2 if 作为表达式:返回值的"条件运算"

在 Rust 中,if-else 不仅是语句,还可以作为表达式 (能返回一个值),类似其他语言的"三元运算符"(Rust 没有 a ? b : c 语法,用 if-else 替代)。

语法规则
  • 所有分支的返回值类型必须一致(否则编译器无法推断最终类型)。
  • 表达式的返回值不需要 return,最后一行代码的结果就是返回值(若最后一行加了 ;,则返回 () 空类型)。
示例 1:获取两个数的最大值
rust 复制代码
fn main() {
    let a = 10;
    let b = 20;

    // if-else 作为表达式,返回最大值并赋值给 max
    let max = if a > b { a } else { b };

    println!("最大值是:{}", max); // 输出:最大值是:20
}
示例 2:错误示范(返回类型不一致)
rust 复制代码
fn main() {
    let flag = true;
    // 错误:一个分支返回 i32,另一个返回 &str,类型不匹配
    let result = if flag { 100 } else { "hello" };
}

二、循环控制:重复执行的"循环赛道"

循环用于让一段代码重复执行,Rust 提供三种循环结构:loop(无限循环)、while(条件循环)、for(遍历循环),覆盖不同场景的重复需求。

2.1 loop:无限循环,手动"刹车"

loop 是最简单的循环,会无限重复执行代码块 ,必须通过 break 手动终止(否则程序会一直运行),适合"不确定循环次数,满足条件就退出"的场景。

基础用法:用 break 终止循环
rust 复制代码
fn main() {
    let mut count = 0;

    loop {
        count += 1;
        println!("当前计数:{}", count);

        // 条件满足时终止循环
        if count == 3 {
            break; // 退出 loop 循环
        }
    }
    // 输出:
    // 当前计数:1
    // 当前计数:2
    // 当前计数:3
}
进阶用法:loop 作为表达式返回值

loop 也可以作为表达式,在 break 后跟上要返回的值(所有 break 的返回值类型需一致),适合"循环中计算结果,退出时返回"的场景。

rust 复制代码
fn main() {
    let mut sum = 0;
    let mut num = 1;

    // loop 表达式返回最终的 sum 值
    let result = loop {
        sum += num;
        num += 1;

        if num > 5 {
            break sum; // 退出循环,返回 sum(此时 sum = 1+2+3+4+5 = 15)
        }
    };

    println!("1到5的和是:{}", result); // 输出:1到5的和是:15
}

2.2 while:条件满足才循环

while 循环会先判断条件表达式 (结果为 bool),若为 true 则执行代码块,否则退出循环,适合"已知循环终止条件,不确定循环次数"的场景。

语法格式
rust 复制代码
while 条件表达式(结果为 bool) {
    // 条件为 true 时执行的代码块
}
示例:遍历数组(不推荐,用 for 更优)
rust 复制代码
fn main() {
    let arr = [10, 20, 30, 40];
    let mut index = 0;

    while index < arr.len() {
        println!("数组元素:{}", arr[index]);
        index += 1; // 手动更新索引,避免死循环
    }
    // 输出:
    // 数组元素:10
    // 数组元素:20
    // 数组元素:30
    // 数组元素:40
}
注意点:避免死循环

while true 等价于 loop,也需要用 break 终止,例如:

rust 复制代码
fn main() {
    let mut count = 0;
    while true {
        count += 1;
        if count == 2 {
            break;
        }
    }
}

2.3 for:遍历集合的"最优解"

for 循环是 Rust 中最常用的循环,主要用于遍历迭代器(Iterator)或集合 (如数组、VecHashMap 等),无需手动管理索引,安全且简洁(避免索引越界问题)。

核心语法:for 变量 in 迭代器/集合 { ... }

Rust 中,所有"可遍历"的类型都实现了 IntoIterator trait,for 循环会自动将集合转换为迭代器,依次取出元素。

示例 1:遍历数组(推荐用法)

直接遍历数组的元素(无需索引),默认是不可变引用 (不转移所有权),若要获取所有权,需用 into_iter();若要可变引用,需用 iter_mut()

rust 复制代码
fn main() {
    let arr = [1, 2, 3, 4];

    // 1. 不可变引用(默认,不转移所有权,arr 后续可继续使用)
    println!("不可变遍历:");
    for elem in arr.iter() {
        println!("{}", elem); // elem 是 &i32 类型,自动解引用打印
    }

    // 2. 转移所有权(arr 后续不可使用)
    println!("转移所有权遍历:");
    let arr2 = [1, 2, 3];
    for elem in arr2.into_iter() {
        println!("{}", elem); // elem 是 i32 类型
    }

    // 3. 可变引用(修改数组元素)
    println!("可变遍历(修改元素):");
    let mut arr3 = [1, 2, 3];
    for elem in arr3.iter_mut() {
        *elem += 10; // 用 * 解引用,修改原元素
    }
    println!("修改后数组:{:?}", arr3); // 输出:[11, 12, 13]
}
示例 2:遍历范围(Range 类型)

Rust 提供 a..b(左闭右开,包含 a 不包含 b)和 a..=b(闭区间,包含 a 和 b)两种范围语法,常用于固定次数的循环。

rust 复制代码
fn main() {
    // 1. 左闭右开:遍历 1,2,3,4(不包含 5)
    println!("左闭右开范围:");
    for num in 1..5 {
        println!("{}", num);
    }

    // 2. 闭区间:遍历 10,11,12(包含 12)
    println!("闭区间范围:");
    for num in 10..=12 {
        println!("{}", num);
    }
}
示例 3:遍历 Vec 集合
rust 复制代码
fn main() {
    let fruits = vec!["苹果", "香蕉", "橙子"];

    // 遍历 Vec 的不可变引用
    for fruit in fruits.iter() {
        println!("水果:{}", fruit);
    }

    // 遍历后 fruits 仍可使用(因为是引用)
    println!("集合长度:{}", fruits.len()); // 输出:3
}

2.4 循环控制:breakcontinue

breakcontinue 是循环中的"控制开关",用于灵活调整循环执行:

  • break:立即终止当前所在的循环(跳出循环体)。
  • continue:跳过当前循环的剩余代码,直接进入下一次循环。
示例:结合 breakcontinue
rust 复制代码
fn main() {
    let mut num = 0;

    loop {
        num += 1;

        // 1. 跳过偶数(不执行后续打印)
        if num % 2 == 0 {
            continue;
        }

        println!("当前奇数:{}", num);

        // 2. 当数字大于 10 时终止循环
        if num > 10 {
            break;
        }
    }
    // 输出:
    // 当前奇数:1
    // 当前奇数:3
    // 当前奇数:5
    // 当前奇数:7
    // 当前奇数:9
    // 当前奇数:11
}

三、实战练习:巩固流程控制用法

通过一个简单的"猜数字游戏",综合运用 if-elseloopbreak 等知识,加深对流程控制的理解。

游戏规则

  1. 程序随机生成一个 1-100 之间的整数。
  2. 用户输入一个数字,程序判断"大了""小了"或"猜对了"。
  3. 猜对后退出循环,游戏结束。

完整代码

rust 复制代码
use std::io;
use rand::Rng; // 需要在 Cargo.toml 中添加 rand 依赖

fn main() {
    println!("欢迎来到猜数字游戏!");
    println!("我已经生成了一个 1-100 之间的数字,快来猜一猜吧~");

    // 1. 生成 1-100 之间的随机数
    let secret_num = rand::thread_rng().gen_range(1..=100);

    // 2. 无限循环,直到猜对
    loop {
        println!("\n请输入你猜的数字:");
        let mut guess = String::new();

        // 3. 读取用户输入
        io::stdin()
            .read_line(&mut guess)
            .expect("无法读取输入");

        // 4. 将输入的字符串转换为整数(处理无效输入)
        let guess: u32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => {
                println!("请输入有效的数字!");
                continue; // 无效输入,跳过后续判断,重新循环
            }
        };

        // 5. 用 if-else 判断大小
        if guess < secret_num {
            println!("你猜的数字太小了!");
        } else if guess > secret_num {
            println!("你猜的数字太大了!");
        } else {
            println!("恭喜你,猜对了!答案就是 {}", secret_num);
            break; // 猜对了,终止循环
        }
    }
}

代码说明

  • 随机数生成 :依赖 rand 库(需在 Cargo.toml 中添加 rand = "0.8"),gen_range(1..=100) 生成 1-100 的闭区间随机数。
  • 输入处理read_line 读取用户输入,parse 转换为整数,若转换失败(如输入字母),用 match 捕获错误并提示,再用 continue 重新循环。
  • 循环终止 :猜对时用 break 退出 loop,游戏结束。

四、总结:流程控制的核心要点

  1. 分支控制if-else 是唯一的分支结构,条件必须是 bool 类型,且支持作为表达式返回值(替代三元运算符)。
  2. 循环控制
    • loop:无限循环,需用 break 终止,支持返回值。
    • while:条件循环,适合"已知终止条件,未知次数"。
    • for:遍历循环,优先用于集合/迭代器,安全简洁(避免索引越界)。
  3. 控制开关break 终止循环,continue 跳过当前轮次。
相关推荐
0和1的舞者2 小时前
力扣hot100-链表专题-刷题笔记(二)
笔记·算法·leetcode·链表·职场和发展
刘孬孬沉迷学习2 小时前
【5G&6G NTN】卫星通信学习系列1
学习·5g·卫星通信·ntn·移动通信·卫星·星地通信
曾几何时`2 小时前
MySQL(四)表的约束
算法
gihigo19982 小时前
竞争性自适应重加权算法
人工智能·算法·机器学习
航Hang*2 小时前
Photoshop 图形与图像处理技术——第9章:实践训练6——滤镜特效
图像处理·笔记·学习·ui·photoshop
FAFU_kyp2 小时前
Rust 模式匹配:match 与 if let 详解
开发语言·后端·rust
renhongxia12 小时前
大型语言模型性能预测器:学习何时在混合人机-人工智能管理系统中升级
人工智能·深度学习·学习·机器学习·语言模型·自然语言处理
知识分享小能手2 小时前
Oracle 19c入门学习教程,从入门到精通,SQL*Plus命令详解:语法、使用方法与综合案例 -知识点详解(4)
sql·学习·oracle
明洞日记2 小时前
【CUDA手册004】一个典型算子的 CUDA 化完整流程
c++·图像处理·算法·ai·图形渲染·gpu·cuda