Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird behaviour when using read_line in a loop

Tags:

rust

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
like image 426
fancyPants Avatar asked Jul 21 '17 08:07

fancyPants


1 Answers

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.

like image 113
Florian Weimer Avatar answered Sep 21 '22 06:09

Florian Weimer