1 前言
本节开始,不区分运行环境是MacOS还是Windows还是Linux
本节完成了一个“猜数字游戏”,也就是系统生成一个数字,用户猜一个数字,系统提示大了或者小了直至猜中
通过本节的学习,可以对语法、风格、库等内容有一个粗略的了解,当然在学习过程中可能会产生更多的问题,问题都会在后续的章节中进行解答
2 代码
强烈建议你直接阅读文档,本文会对我学习过程中的一些关注点进行梳理,总结尽量准确,如果内容有偏差不准确处可以提出,我会进行修订,感谢
这里先直接放上最终完整版的,经过chatgpt和我注释的代码,新建项目,完成修改后,可以cargo run
直接运行
// main.rs 文件
// 导入 rand 模块中的 Rng trait
use rand::Rng;
// 导入 std 库中的 cmp 模块的 Ordering 枚举
use std::cmp::Ordering;
// 导入 std 库中的 io 模块
use std::io;
fn main() {
// 打印猜数字的欢迎消息
println!("Guess the number!");
// 生成一个随机的秘密数字,范围是 1 到 100(不包括 101)
let secret_number = rand::thread_rng().gen_range(1..101);
// 用于调试,打印秘密数字
// println!("The secret number is: {}", secret_number);
// 进入循环,直到猜中为止
loop {
// 提示用户输入猜测
println!("Please input your guess.");
// 创建一个可变的字符串来存储用户的猜测
let mut guess = String::new();
// 从标准输入读取用户的猜测,并将其存储到 guess 变量中
io::stdin()
.read_line(&mut guess)
.expect("Fail to read line");
// 将用户输入的字符串转换为无符号整数(u32),如果失败则继续下一次循环
let guess: u32 = match guess.trim().parse() {
Ok(num) => num, // 异常处理,num类型则读取
Err(_) => continue, // 异常处理,非num类型则继续下一个循环而不直接失败,'_'是通配符
};
// 打印用户的猜测
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;
}
}
}
}
# Cargo.toml 文件
# 指定包的元数据
[package]
name = "guessing_game" # 包的名称
version = "0.1.0" # 包的版本
edition = "2021" # Rust 编译器版本
# 更多键和它们的定义可以在以下链接找到:https://doc.rust-lang.org/cargo/reference/manifest.html
# 指定项目的依赖关系
[dependencies]
rand = "0.8.3" # 依赖 rand 库的版本号,Cargo 会根据这个版本号下载相应的库
3 重点
3.1 风格
1、默认使用4个空格进行缩进,而不是制表符
2、每句的结尾必须使用;
3、多个枚举值场景判断之间用,
3.2 语法
1、变量定义。用let
定义,默认为不可变的变量,加上mut
也就是mutability
则是可变变量
2、变量类型。可以通过String::new()
来给变量初始化为字符串类型,值得说明的是,变量类型是根据内容进行推断的,且不可变,具体会在后续章节展开
3、变量引用。&
表示引用,使不同的代码访问同一数据且无需内存拷贝,如果访问的是可变的变量,需要&mut guess
4、异常处理。会产生Result
的枚举值,包含Ok
和Err
。可以使用expect
进行异常处理,也可以对Ok
与Err
分别处理
5、比较。使用cmp
方法,注意不同类型的变量无法比较,比如字符串与数字,所以需要先转化成相同的类型。
6、匹配。使用match
方法,代码中的Result
(Ok
、Err
),Ordering
(Less
、Greater
、Equal
)都是枚举值。一个match
拥有多个分支(arm),每一个分支都是一种匹配模式(pattern)以及对应的处理逻辑。
3.3 库
1、通过use
的方式引入。
2、std
的库可以直接引入。
3、非std
的库,需要在toml中添加dependencies
,并指定对应的版本。0.8.3
的意思实际是^0.8.3
,也即至少0.8.3
但不大于0.9.0
的版本。
4、cargo build
会生成一个Cargo.lock
的文件,指定版本,从而能重现构建,直到你显式地升级依赖的版本。
5、cargo update
会忽略Cargo.lock
,并使用目前基于Cargo.toml
的最新版本,并更新Cargo.lock
6、值得注意的是,本次虽然之引入rand
这一个非std的库,但是cargo
会自动地获取其所以来的其他所有的库来保证能正常运行
7、by the way 补一嘴,cargo中,依赖是从registry
上获取,是来自Crates.io
的数据拷贝,Crates.io
是Rust生态环境下,开发者们贡献Rust开源项目的地方。
3.4 其他
chatgpt不一定准确,通过chatgpt注释上面的代码检查时有发现错误…但是可以参考
4 问题
相信看完这一章,还会有很多的问题
比如变量有哪些类型,怎么定义、某些场景下能不能转换、rust的引用是怎么用的、怎么定义函数、::
与.
在方法使用和引入上分别是什么意思,比较复杂的代码用什么方式编写,crate
怎么使用与管理、枚举值、输入输出等等等等
本节只是一个简单的引入,这些问题会在后面的章节中,逐步展开