Rust从入门到实战系列二十:处理无效输入

为了进一步改善游戏性,不要在用户输入非数字时崩溃,需要忽略非数字,让用户可以继续猜测。可以通过修改 guess 将 String 转化为 u32 那部分代码来实现:

# use std::cmp::Ordering;
# use std::io;
#
# fn main() {
# println!("Guess the number!");
#
# 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();
#
// --snip--
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);
// --snip--
#
# match guess.cmp(&secret_number) {
# Ordering::Less => println!("Too small!"),
# Ordering::Greater => println!("Too big!"),
# Ordering::Equal => {
# println!("You win!");
# break;
# }
# }
# }
# }

我们将 expect 调用换成 match 语句,以从遇到错误就崩溃转换为处理错误。须知 parse 返回一个Result 类型,而 Result 是一个拥有 Ok 或 Err 成员的枚举。这里使用的 match 表达式,和之前处理 cmp方法返回 Ordering 时用的一样。
如果 parse 能够成功的将字符串转换为一个数字,它会返回一个包含结果数字的 Ok。这个 Ok 值与match 第一个分支的模式相匹配,该分支对应的动作返回 Ok 值中的数字 num,最后如愿变成新创建的guess 变量。
如果 parse 不能将字符串转换为一个数字,它会返回一个包含更多错误信息的 Err。Err 值不能匹配第一个 match 分支的 Ok(num) 模式,但是会匹配第二个分支的 Err(_ ) 模式:_ 是一个通配符值,本例中用来匹配所有 Err 值,不管其中有何种信息。所以程序会执行第二个分支的动作,continue 意味着进入loop 的下一次循环,请求另一个猜测。这样程序就有效的忽略了 parse 可能遇到的所有错误!
现在万事俱备,只需运行 cargo run:

Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 4.45s
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 61
Please input your guess.
10
You guessed: 10
Too small!
Please input your guess.
99
You guessed: 99
Too big!
Please input your guess.
foo
Please input your guess.
61
You guessed: 61
You win!

太棒了!再有最后一个小的修改,就能完成猜猜看游戏了:还记得程序依然会打印出秘密数字。在测试时还好,但正式发布时会毁了游戏。删掉打印秘密数字的 println!。

use std::cmp::Ordering;
use std::io;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1..101);
loop {
println!("Please input your guess.");

使用循环来允许多次猜测 53

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;
}
}
}
}

总结
此时此刻,你顺利完成了猜猜看游戏。恭喜!
本项目通过动手实践,向你介绍了 Rust 新概念:let、match、函数、使用外部 crate 等等,接下来的几章,你会继续深入学习这些概念。第三章介绍大部分编程语言都有的概念,比如变量、数据类型和函数,以及如何在 Rust 中使用它们。第四章探索所有权(ownership),这是一个 Rust 同其他语言大不相同的功能。第五章讨论结构体和方法的语法,而第六章侧重解释枚举。

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值