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
並且程式按預期退出!