本小节目标
判断用户输入与目标数字是否匹配并反馈结果.
控制语句
请复制到本地:
use rand::random_range;
use std::io;
fn main() {
println!("请猜测一个数");
let secret_num = random_range(1..=100);
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("读取有误时的报错");
println!("你猜的是: {}", guess);
// vvvv 新增代码 vvvv
if guess == secret_num.to_string() {
println!("猜对了");
} else {
println!("猜错了");
}
// ^^^^ 新增代码 ^^^^
}在这部分代码中, 我们调用 i32 类型上定义的 .to_string() 方法将 secret_num 转化为 String 类型, 然后通过形式
if /* 任意返回布尔值的表达式 */ {
/* 布尔值为真时执行该语句块 */
}
else
{
/* 布尔值为假时执行该语句块 */
}分情况执行不同代码. 我们代码中的 guess == secret_num.to_string() 作为表达式返回的就是 布尔 (bool) 类型, 该类型专门用于逻辑判断, 仅有 true 和 false 两个值. 而 == 运算符专门用于比较两个相同类型变量是否具有相同的值, 也正因此必须首先将 i32 类型的 secret_num 转为 String 类型, 然后才能与 IO 输入的 String 类型变量 guess 相比较.
else {..} 语句块作为布尔表达式为假的分支, 整体允许省略, 即写为
if /* .. */ {
/* .. */
}此时如果布尔表达式为假, 语句块将被单纯地跳过.
注意
在 C/C++ 中, 布尔表达式必须用括号包裹, 而执行语句块若只有单句则可以略去大括号, 如
if (a == 1)
a-=2;Rust 恰好与之相反, 布尔表达式允许 (甚至建议) 非必要时略去布尔表达式的括号, 但禁止省略执行语句块的大括号. 如果执意写
if (a == 1)
{
a = a - 2;
}代码检查器甚至会警告称
unnecessary parentheses around `if` condition
`#[warn(unused_parens)]` (part of `#[warn(unused)]`) on by default模式匹配
上面的例子用到与 C/C++ 类似的 if-else 控制语句去控制分支, 但在 Rust 中, 更优雅的做法是使用模式匹配. 请复制代码到本地:
use rand::random_range;
use std::{cmp::Ordering, io};
fn main() {
println!("请猜测一个数");
let secret_num = random_range(1..=100);
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("读取有误时的报错");
println!("你猜的是: {}", guess);
match guess.cmp(&secret_num.to_string()) {
Ordering::Less => println!("太小了!"),
Ordering::Greater => println!("太大了!"),
Ordering::Equal => println!("猜对了!"),
}
}这其中, .cmp() 是定义在泛型参数 T 上的方法, 功能也是比较两个相同类型的变量, 接收两个相同类型的引用参数 (&self, &other:Self), 然后返回一个枚举类型 Ordering. Ordering 定义在 std::cmp::Ordering 上, 有三个可能的变体, 即 Ordering::Less, Ordering::Greater 和 Ordering::Equal.
match 关键字将对返回枚举类型的表达式模式匹配, 在其后的大括号语句块中以 , 分隔依次匹配每个枚举结果, 成功匹配后执行枚举结果对应行 => 后的语句. 模式匹配的强大之处将在后文详细介绍, 此处的确与 if-else 区别不算大.
花活
上述代码的 match 部分由于 Rust 的表达式特性可以写作如下形式:
println!(
"{}",
match guess.cmp(&secret_num.to_string()) {
Ordering::Less => "太小了",
Ordering::Greater => "太大了",
Ordering::Equal => "猜对了",
}
)合并 use 语句
注意到代码中引入外部包的写法是
use std::{cmp::Ordering, io};这种写法与
use std::cmp::Ordering;
use std::io;完全等价.