Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
543 views
in Technique[技术] by (71.8m points)

mut String redeclaration inside loop

I'm reading the Rust book and the guessing game tutorial has the following code:

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!("
You guessed: {}", guess);

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

This code fails after the first user input. If I move the let mut input = String::new(); declaration inside the loop then everything is ok... But I'm wondering why I have to do that since the address of input is passed into read_line()?

And one more thing why do I have to use std::io::Write in order to use io::stdout().flush().unwrap(); since I'm already using use std::io;?

question from:https://stackoverflow.com/questions/65865824/mut-string-redeclaration-inside-loop

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
io::stdin().read_line(&mut input);

This method doesn't overwrite the String but it appends to the String. This is why only the first iteration of the loop works but it immediately breaks on the second iteration. If you want to re-use the String buffer between iterations you need to truncate it before passing it back into read_line. Fixed working example:

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!("
You guessed: {}", guess);

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

And one more thing why do I have to use std::io::Write in order to use io::stdout().flush().unwrap(); since I'm already using use std::io;?

In order to call trait methods you need to bring the trait into scope. flush is defined by the Write trait.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...