Rust 初学者/基础数学测试程序/字符串到数字
外观
现在我们已经从标准输入中读取了一个字符串。但我们想要将其转换为数字。为此,我们在 i32 内部使用以下函数
fn from_str_radix(src: &str, radix: u32) -> Result<i32, ParseIntError>
src 是我们要转换为数字的字符串。radix 是我们要转换到的数字的基数。我们只想要使用 10 进制,因为这是人们输入的方式。此外,该函数返回一个 Result,表明该函数可能会失败。我们可以在结果上使用 .unwrap(),但这意味着如果用户输入了任何无法转换为数字的内容,程序就会崩溃。相反,我们希望正确处理错误,如果用户输入无法转换为数字,我们应该要求用户重新输入。以下是示例代码
fn wait_for_input() -> i32 {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).unwrap();
let mut result = i32::from_str_radix(&buffer, 10);
while let Err(_) = result {
println!("Invalid number, please re-enter:");
buffer.clear();
io::stdin().read_line(&mut buffer).unwrap();
result = i32::from_str_radix(&buffer, 10);
}
let num = result.unwrap();
num
}
请注意,我们在结果为错误时循环,因此最后面的 unwrap 始终是安全的。此外,我们必须在每次运行之间清除缓冲区。现在让我们测试一下,看看它是如何工作的!
What is 35 - 23? 5 Invalid number, please re-enter: 12 Invalid number, please re-enter: 6 Invalid number, please re-enter:
糟糕。请注意,我们在循环中使用 Ctrl-C 来退出程序。但问题是什么?为什么它无法正确解析字符串为数字?让我们添加一个调试 println!() 语句来查看 buffer 的值在解析之前是什么
println!("buffer: {:?}", buffer);
然后当我们运行它时,它会打印出
What is 35 - 23? 10 buffer: "10\r\n" Invalid number, please re-enter:
字符串末尾的那些字符是什么?实际上,由于我们必须按 Enter 提交数字,这会向标准输入添加一个换行符,该换行符包含在缓冲区中。另一个令人讨厌的事情是换行符取决于你的操作系统,Windows 通常使用 “\r\n”,而其他操作系统使用 “\n”。我们想要处理这两种情况,因此我们将添加一行代码来用空字符串替换所有这些字符,因此我们的函数变为
fn wait_for_input() -> i32 {
let mut buffer = String::new();
io::stdin().read_line(&mut buffer).unwrap();
buffer = buffer.replace("\r", "").replace("\n", "");
let mut result = i32::from_str_radix(&buffer, 10);
while let Err(_) = result {
println!("Invalid number, please re-enter:");
buffer.clear();
io::stdin().read_line(&mut buffer).unwrap();
buffer = buffer.replace("\r", "").replace("\n", "");
result = i32::from_str_radix(&buffer, 10);
}
let num = result.unwrap();
num
}
现在我们的函数可以正常工作了,当我们运行它时,我们会得到这些结果
What is 35 - 23? test Invalid number, please re-enter: 1s3r Invalid number, please re-enter: 10
并且程序按预期退出!