mut String 在循环内重新声明

问题描述

我正在阅读 Rust 书,猜谜游戏教程有以下代码

use rand::Rng;
use std::cmp::Ordering;
use std::io;
use std::io::Write;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1,101);
    let mut input = String::new();

    loop {
        print!("Guess the number I'm thinking of: ");
        io::stdout().flush().unwrap();
        io::stdin().read_line(&mut input).expect("Failed to read line");

        let guess: u32 = match input.trim().parse() {
            Ok(num) => num,Err(_) => continue
        };

        println!("\nYou guessed: {}",guess);

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),Ordering::Greater => println!("Too big!"),Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}

代码在第一次用户输入后失败。如果我将 let mut input = String::new(); 声明移动到循环内,那么一切都很好......但我想知道为什么我必须这样做,因为 input 的地址被传递到 read_line() 中?

还有一件事,为什么我必须使用 std::io::Write 才能使用 io::stdout().flush().unwrap();,因为我已经在使用 use std::io;

解决方法

io::stdin().read_line(&mut input);

此方法不会覆盖 String,但会附加到 String。这就是为什么只有循环的第一次迭代有效,但它在第二次迭代时立即中断。如果您想在迭代之间重新使用 String 缓冲区,您需要在将其传递回 read_line 之前将其截断。固定工作示例:

use rand::Rng;
use std::cmp::Ordering;
use std::io;
use std::io::Write;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1,101);
    let mut input = String::new();

    loop {
        print!("Guess the number I'm thinking of:");
        io::stdout().flush().unwrap();
        
        input.clear(); // truncate String buffer here!

        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");

        let guess: u32 = match input.trim().parse() {
            Ok(num) => num,Err(_) => continue,};

        println!("\nYou guessed: {}",guess);

        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),Ordering::Greater => println!("Too big!"),Ordering::Equal => {
                println!("You win!");
                break;
            }
        }
    }
}

还有一件事,为什么我必须使用 std::io::Write 才能使用 io::stdout().flush().unwrap();,因为我已经在使用 std::io;

为了调用 trait 方法,你需要将 trait 引入作用域。 flushWrite 特征定义。