Rust_GuessingGame

  • 一般crate使用use导入, 但是Rust会自动导入prelude,里面包含了基本的功能, 详见standard library documentation.

  • Rust中的变量默认是不可变的, 可以添加mut关键字使之改变

  • read_line读取用户输入,并将其添加到字符串尾端(append), 而不是覆盖, 不同于cin

  • read_line会返回一个Result值

  • Result是一个枚举类型,其中有OkErr, 所以可以使用read_line(&mut guess).expect("Failed to read") expect函数来处理错误读入, 任何类型的值都有其方法

  • 正常情况下,expect()方法会返回用户输入的字节数

  • println!() 可以使用{}来输出变量, 但是如果变量名称不存在就会报错

  • crate是一组Rust源代码文件,用户构建的项目是一个二进制crate, 它是一个可执行文件. rand crate是一个库crate, 它包含的代码用于其他程序, 并不能单独运行

  • Semanic Versioning

    • 核心规则是一个三部分版本号: MAJOR. MINOR. PATCH(主版本号, 次版本号, 修订号).
    • PATCH (修订号):当你做了向后兼容的 Bug 修复时,增加修订号。例如,从 1.0.01.0.1。这意味着使用 1.0.0 的代码升级到 1.0.1 时,不会出现编译错误或运行时问题。
    • MINOR (次版本号):当你做了向后兼容的新功能添加时,增加次版本号。例如,从 1.0.01.1.0。这意味着你在不破坏现有公共 API 的情况下增加了新功能。旧代码仍然可以正常工作,并且可以利用新功能。
    • MAJOR (主版本号):当你做了不兼容的 API 更改时(即引入了破坏性变更),增加主版本号。例如,从 1.0.02.0.0。这意味着使用 1.0.0 的代码在升级到 2.0.0 时可能会出现编译错误或运行时问题,需要修改代码以适应新的 API。

    Rust 生态系统与 SemVer 的关系:

    1. Cargo 的核心原则:Rust 的包管理器 Cargo 默认高度依赖 SemVer。当你将一个 crate(Rust 中的包)添加到 Cargo.toml 文件的依赖项中时,例如 my_crate = "1.2.3",Cargo 会根据 SemVer 规则自动解析并选择一个兼容的版本。这极大地简化了依赖管理,因为开发者可以相对放心地升级次版本和修订版本,而不用担心代码中断。
    2. 0.y.z 版本的特殊性:根据 SemVer 规范,主版本号为 0 的版本(即 0.y.z)被视为处于初始开发阶段,此时即使是次版本号的增加(如从 0.1.00.2.0)也可以引入破坏性变更。这是因为在 1.0.0 之前,API 稳定性通常还不被保证。不过,在 Cargo 中,对于 0.x.y 形式的版本,0.x.z 被认为是与 0.x.y 兼容的(当 z >= yx > 0 时),这与标准 SemVer 对 0.y.z 的处理略有不同。
    3. 自动化工具:由于手动遵守 SemVer 规则可能非常复杂且容易出错,Rust 社区开发了像 cargo-semver-checks 这样的自动化工具。这些工具可以分析你的 crate 代码与最新发布版本之间的差异,并自动检测是否存在违反 SemVer 规则的破坏性变更,从而帮助开发者在发布新版本之前发现并解决问题。
  • gen_range(1..=100) 随机数生成[1, 100]

  • match语句在第一次匹配之后结束

  • let mut guess = String::new();
    
    io::stdin()
        .read_line(&mut guess)
        .expect("Failed to read line");
    let guess: u32 = guess.trim().parse().expect("Please type a number!")	// Rust中可以使用新变量覆盖旧变量, 此行作用是将guess转为u32类型
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    `trim()`方法用来消除字符串收尾的空白字符,`\n` `\r`等等

    `parse()`方法用来将字符串转换成另一个类型

    + ```rust
    let guess: u32 = match guess.trim().parse() {
    Ok(num) => num, // 注意这里用的逗号
    Err(_) => continue, // _(下划线)代表获取所有值
    };

整体完成的代码, guessing_name.rs

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
32
33
34
35
36
use std::cmp::Ordering;
use std::io;

use rand::Rng;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1..=100);

loop {
println!("Please input your number");

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(_) => continue,
};

println!("You guessed: {guess}");

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}