From 707f3c92895ee12b238a5deb5fc861cc20d03c55 Mon Sep 17 00:00:00 2001 From: "rust-lang.xfoss.com" Date: Thu, 7 Dec 2023 13:22:04 +0800 Subject: [PATCH] Refining Ch02. --- src/Ch02_Programming_a_Guessing_Game.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Ch02_Programming_a_Guessing_Game.md b/src/Ch02_Programming_a_Guessing_Game.md index 98b71d1..4b6d58e 100644 --- a/src/Ch02_Programming_a_Guessing_Game.md +++ b/src/Ch02_Programming_a_Guessing_Game.md @@ -579,9 +579,20 @@ error: could not compile `guessing_game` due to previous error let guess: u32 = guess.trim().parse().expect("请输入一个数字!"); ``` -这里创建了一个名为 `guess` 的变量。不过稍等一下,这个程序不是已经有了一个名为 `guess` 的变量了吗?他确实已经有了个名为 `guess` 的变量,然而好在 Rust 是允许以一个新的 `guess` 变量,对其先前的值进行 *遮蔽(shadow)* 操作的。这样的遮蔽特性,实现了对`guess` 这个变量名的重用,而非强制创建两个诸如 `guess_str` 和 `guess` 这样的独特变量。在第 3 章将对此进行更详细的讲解,此时只要明白,此特性通常用在要将某个值从一种类型转换到另一类型的时候。 +我们创建了一个名为 `guess` 的变量。但是等等,程序中不是已经有一个名为 `guess` 的变量了吗?是有的,但好在 Rust 允许我们用一个新值,对 `guess` 的前一个值进行遮蔽处理。*遮蔽特性,shadowing* 允许咱们,重复使用这个 `guess` 变量名,而不必被迫创建出,诸如 `guess_str` 和 `guess` 这样的两个唯一变量。我们将在 [第 3 章](programming_concepts/variables_and_mutability.md#遮蔽shadowing) 中详细介绍这一功能,而现在我们要知道,当咱们打算将某个值,从一种类型转换为另一类型时,就经常会用到这一特性。 + +我们将这个新变量,绑定到 `guess.trim().parse()` 这个表达式。表达式中的 `guess`,指的是包含了作为字符串的输入的那个原始 `guess` 变量。某个 `String` 实例上的 `trim` 方法,将消除开头和结尾的空白,我们必须这样做才能将字符串与 `u32` 进行比较,而 `u32` 只能包含数字数据。用户必须按下回车键,来满足 `read_line` 并输入他们的猜数,这会添加一个换行符到输入字串。例如,如果用户输入 5 并按回车键,`guess` 就会看起来是这样的:`5\n`。`\n` 表示 “换行/newline”。(在 Windows 系统中,按下回车键会产生是回车和换行,即 `\r\n`)。译注 1 `trim` 方法可以去掉 `\n` 或 `\r\n`,结果就只有 `5` 了。 + +> **译注 1**:这也是为何先前的代码: +> +```rust + let bytes = io::stdin() + .read_line(&mut guess) + .expect("读取行失败/failed to read line"); +``` +> +> 在 Windows 的 MSYS2 上运行时,`bytes` 的输出始终会比咱们看到的字符串,要多两个字节的原因。 -这里将这个新变量,绑定到了表达式 `guess.trim().parse()`。该表达式中的 `guess` 援引的是原来那个包含着字符串形式输入的 `guess`。而作用在 `String` 实例上的 `trim` 方法,将消除开头和结尾的全部空白,必须要进行这个操作,才能将字符串转换到 `u32` 类型,`u32`只能包含数字数据。为了满足到 `read_line` 并输入他们的猜数,用户必须要按下回车键,这样就会将一个换行字符添加到那个字符串。比如在用户敲入了 `5` 然后按下回车键时,`guess`看起来就会是这样:`5\n`。其中的 `\n` 表示 “换行(newline)”。(在 Windows 上,按下回车键会导致一个回车字符和一个换行字符,即 `\r\n`)。这 `trim` 会将 `\n` 或 `\r\n` 消除,而结果就只是 `5` 了。 [字符串上的 `parse` 方法](https://doc.rust-lang.org/std/primitive.str.html#method.parse) 将只会在那些逻辑上可被转换成数字的字符上运作,而因此就很可能引起错误。比如说在字符串包含了 `A👍%` 时,就没有办法将其转换成一个数字。由于 `parse` 方法会失败,因此他返回的是个 `Result` 类型,这与 `read_line` 方法所做的一样(在早先的 [用 `Result` 类型处理潜在失败](#处理潜在的带有-result-的程序失效) 中讨论过)。这里再次使用 `expect` 方法对这个`Result` 进行了同样的处理。在因为 `parse` 无法从字符串创建出一个数字,而返回了一个 `Err` 的 `Result` 变种时,这个 `expect` 就会令到游戏崩溃,并将给他的那条消息打印出来。而在 `parse` 可成功将那个字符串,转换成数字时,`expect` 就会返回 `Result` 的 `Ok` 变种,同时 `expect` 会返回这里想要的、`Ok` 值中的数字。