在循环中使用read_line时的奇怪行为

fan*_*nts 3 rust

我在Rust中的第一个程序应该以字符的形式从用户那里获取输入,C或F:

use std::io;

fn main() {
    let mut srcunit = String::new();

    let mut switch = true;
    while switch {
        println!("source unit? F or C?");
        io::stdin().read_line(&mut srcunit).expect(
            "failed to read src unit",
        );

        if srcunit.trim() == "F" || srcunit.trim() == "C" {
            println!("doing things right with {}", srcunit);
            switch = false;
        } else {
            println!("either F or C, not {}", srcunit);
        }
    }

    println!("you pressed {}", srcunit);
}
Run Code Online (Sandbox Code Playgroud)

当我启动程序并按F或C时,它工作正常,所以我在这里跳过它.当我按下另一个角色时,奇怪的部分出现了.我希望我的程序再次询问F或C,直到我按下其中一个字符.当我这样做时,它应该离开while循环并告诉我我按下了什么.

source unit? F or C?
G
either F or C, not G //so far so good

source unit? F or C?
F
either F or C, not G //why is F not assigned to the srcunit variable? It's supposed to leave the loop now.
F                    //why does it print this line? I didn't press a key or have a println function/macro that does this

source unit? F or C?
V
either F or C, not G //it's still G, wtf
F                    //again, why are those two lines printed? Where does it store, that I pressed F previously?
V
Run Code Online (Sandbox Code Playgroud)

Flo*_*mer 6

从以下文档read_line:

读取所有字节,直到达到换行符(0xA字节),然后它们附加到提供的缓冲区.

(强调我的.)你需要在读取下一行之前清除字符串,例如通过调用clear()字符串上的方法,否则答案将累积在变量中.

或者,您可以在循环中定义变量(但这样效率稍低,因为这样,String将无法为下一个答案重用已分配的存储,必须重新分配并重新分配).

最近也问到了这个问题.看起来这是一个常见的陷阱.

  • [该示例]中的关键示例(https://doc.rust-lang.org/book/second-edition/ch02-00-guessing-game-tutorial.html#allowing-multiple-guesses-with-looping)(希望我得到正确的链接)是变量在循环中声明,因此每次迭代都会自动重新创建. (2认同)