Weird behaviour when using read_line in a loop

2020-02-07 04:17发布

My first program in Rust is supposed to take input from the user in the form of characters, either C or 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);
}

When I start the program and press either F or C, it works right, so I'm skipping this here. The weird part comes when I press another character. I expect my program to ask again for either F or C until I press one of those characters. When I do, it should leave the while loop and tell me what I've pressed.

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

标签: rust
1条回答
冷血范
2楼-- · 2020-02-07 04:43

From the documentation for read_line:

Read all bytes until a newline (the 0xA byte) is reached, and append them to the provided buffer.

(Emphasis mine.) You need to clear the string before reading the next line, for example by calling the clear() method on the string, otherwise the answers are accumulated in the variable.

Alternatively, you can define the variable in the loop (but this is slightly less efficient because this way, String will not be able to reuse the already allocated storage for the next answer, it has to be deallocated and reallocated again).

See also this question, asked recently. Looks like this is a common trap.

查看更多
登录 后发表回答