• rust入门基础案例:猜数字游戏


    案例出处是《Rust权威指南》,书中有更加详细的解释。从这个例子中,我们可以了解到 rust 的两个操作:

    1. 如何从控制台读取用户输入
    2. rust 如何生成随机数

    代码格式化

    编译器可在保存时对代码做格式化处理,底层调用 rustfmt 来实现,代码内容基本和书中内容一致。代码中使用 use 语句显示的导入了标准库 std 中的 iocmp 包,因为 rand包并不在标准库中,所以,我们在 dependencies 声明中引入 rand 包。

    use rand::Rng;
    use std::{cmp::Ordering, io};
    
    fn main() {
        let secret_number = rand::thread_rng().gen_range(1, 101);
    
        loop {
            let mut guess = String::new();
            io::stdin()
                .read_line(&mut guess)
                .expect("failed to read line");
    
            let guess: u32 = match guess.trim().parse() {
                Ok(num) => num,
                Err(err) => {
                    println!("parse error: {err}");
                    continue;
                }
            };
    
            match guess.cmp(&secret_number) {
                Ordering::Equal => {
                    println!("success");
                    break;
                }
                Ordering::Greater => println!("too big"),
                Ordering::Less => println!("too small"),
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    从控制台读取输入

    io::stdin() 中的::语法声明stdin是io类型的一个关联函数,rust 会针对类型本身来定义函数,而不是针对某个特定实例,同样还有 String::new() 方法调用。

    read_line 将控制台输入的内容存储到传入的参数中,同时返回 io::Result 类型值。这个类型属于枚举类型,rust 主要用来做错误处理。

    生成随机数

    针对 dependencies 中 rand 包的声明,rust 按照标准的语义化版本来处理版本号。版本声明中的 0.3.14实际上是^0.3.14的一个简写,它表示“任何与0.3.14版本公共API相兼容的版本”

    [dependencies]
    rand = "0.3.14"
    
    • 1
    • 2

    程序最终使用的 rand 版本会记录在 Cargo.lock 文件中,通过 Cargo.lock 中详细的版本依赖信息,才保证了我们任何时候编译的结果都是相同的。除第一次构建程序外,再次构建程序时,Cargo 会优先检查 Cargo.lock,假如文件中存在已经指明具体版本的依赖库,那么它就会跳过计算版本号的过程,并直接使用文件中指明的版本。这使得我们拥有了一个自动化的、可重现的构建系统。

    下面记录了 Cargo.lock 中记录了项目依赖的 rand 包详细信息:

    在这里插入图片描述

    当你确实想要升级某个依赖包时,Cargo提供了一个专用命令:update,它会强制Cargo忽略Cargo.lock 文件,并重新计算出所有依赖包中符合Cargo.toml 声明的最新版本。假如命令运行成功,Cargo就会将更新后的版本号写入Cargo.lock文件,并覆盖之前的内容。

    cargo doc

    这里推荐另一个指令 : cargo doc --open,前面的例子中有讲到 rustup doc,cargo doc 会本地构建一份项目依赖的文档,并自动在浏览器中打开供你查看。

    对于自动生成的依赖文档,我们期待里面直接包含了 rand、io、cmp 的 API 说明,至少包含 dependencies 中明确声明的依赖包。但生成的文档中,可能只包含了 guess 这一个主包的文档,压根不符合我们的预期。

    我们通过它的属性列表来一一试探一下:

    在这里插入图片描述

    • cargo doc 生成的文档依赖 manifest 文件中声明的 workspace,manifest 指代项目的 Cargo.toml 文件,当前项目的 manifest 中并没有声明 workspace 区块。 查看 workspace 的使用文档,主要是定义项目内存在多个自定义包的情况,rand、cmp 不再这个范围内,所以属性 ----workspace 没有什么效果。
    • cargo doc --package 'rand@0.3.23' --open 通过属性 package 明确指定了文档中的包名,浏览器正常的输出了 rand 包的 API。

    在这里插入图片描述

    方法 gen_range 生成的随机数包含下限不包含上限,所以代码中指定了1和101来获取1到100间的随机整数。

    正常生成伪随机数都需要初始化 seed,如果不做初始化,每次生成的随机数都是相同的。thread_rng 方法内部把 seed 的封装了。如果使用相同的对象会生成相同的随机数吗?下面的代码最终生成的 3 个变量是不相同的。

     let thread_rng = rand::thread_rng();
     let secret_number = thread_rng.clone().gen_range(1, 101);
     let secret_number_1 = thread_rng.clone().gen_range(1, 101);
     let secret_number_2 = thread_rng.clone().gen_range(1, 101);
     println!("{}-{}-{}", secret_number, secret_number_1, secret_number_2);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    类型转换

    代码中将字符串类型转换为 u32 类型,这种字符串类型转换的方式直接通过类型声明来实现。而且,guess 变量也是重新声明的 u32 类型,隐藏了之前字符串类型的变量。

    let guess: u32 = match guess.trim().parse()
    
    • 1

    下面给变量 x 重新赋值,rust 编译会报错:cannot mutate immutable variable,不可以对不可变量进行修改。侧面说明,x 属于不可变量。

    fn main() {
        let x: i32 = 5;
        x = 6;
    }
    
    • 1
    • 2
    • 3
    • 4

    下面通过 let 重新声明变量的方式模拟实现了重新赋值,但实际上,第一个变量只是被第二个变量掩藏了。这个过程中,let 其实是创建了新的变量,所以,我们可以在复用变量名称的同时,修改它的类型。

    fn main() {
        let x: i32 = 5;
        let x: u32 = 6;
    }
    
    • 1
    • 2
    • 3
    • 4

    总结

  • 相关阅读:
    Python类中的property的用法
    浅析倾斜摄影三维模型(3D)几何坐标精度偏差的几个因素
    简单来说,无人机单片机是如何控制电机的?
    设计高并发秒杀系统:保障稳定性与数据一致性
    Git基础命令
    springboot中自定义JavaBean返回的json对象属性名称大写变小写问题
    【NLP】第14章 解释黑盒Transformer模型
    学习笔记-SSTI
    Android 调试桥——ADB
    金九失足,10月喜提“Java高分指南”,11月冲击大厂
  • 原文地址:https://blog.csdn.net/f1520107395/article/details/134225131