loop{} is running twice?

Viewed 220

I have fully coded the program from "The Rust Programming Language" book online, chapter 2. I have also developed it a tiny bit further than provided: by adding a simple question/response where the user gets to play again by inputting "y".

However, I am experiencing a slight bug in my program. When a user opts to run the game again, the text output "Please input a (number) guess" is repeated twice. Of course, this does not take away from the main functionality of the program (it still functions fine after the repeat), but it does seem weird and I'd prefer to remove the issue now rather than leaving it.

I have done some debugging, which has resulted in me concluding it is definitely happening in the [figure 3] area in the code. To see how I did so, go to the debugging area below.

Code

extern crate rand;
#[macro_use]
extern crate text_io;

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

//Main code
fn main() {
    // Generate random number, create premise
    println!("Guess the number!");
    let mut breaking_choice = false;
    while !breaking_choice {
        let secret_number = rand::thread_rng().gen_range(1, 101);
        // **Problem area**
        loop {
            println!("Please input a (number) guess");
            println!("1"); // [**REFERENCE 1**]
            let mut guess = String::new();
            io::stdin()
                .read_line(&mut guess)
                .expect("Failed to read line");
            println!("2"); // [**REFERENCE 2**]
            let guess: u32 = match guess.trim().parse() { // [FIGURE 3]
                Ok(num) => num,                           // [FIGURE 3]
                Err(_) => continue,                       // [FIGURE 3]
            };

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

        // **Possible problem area**
        println!("Would you like to continue playing? Y or N");
        let choice: String = read!();

        if choice == "N" {
            breaking_choice = true
        } else if choice == "n" {
            breaking_choice = true
        } else if choice == "Y" {
            continue;
        } else if choice == "y" {
            continue;
        }
    }
}

Debugging

The first thing I did was place some simple println! commands at the main processing areas of the questionable code: [Reference 1] and [Reference 2]. This allowed me to see whether any of the commands were the problem in between them to give me a slightly better angle as to what is happening. I also replaced the random number generator with a set number (let secret_number = 5;)

This is what happened in compilation:

and this is what happened in execution:

From these results, I believe that the error is occurring in [FIGURE 3] (main input verification) because that is where it seems to stop.

I have put println!("3"); just before //...until correct, which doesn't output in the first loop. Therefore, it is at [FIGURE 3] that the program is having the problem.

1 Answers

I guess pressing enter leads to CRLF (\r\n) (on Windows; on Linux it seems to work fine), i.e. two whitespace characters. read! will only read one of them, and the next read_line call will return an empty line (string with only \n (0x0a)).

Related