Home > Software engineering >  stdin don´t wait for users input in rust loop
stdin don´t wait for users input in rust loop

Time:01-22

Why stdin().read_line(&mut next_string); does not wait for the input? It looks like it was skipped. It go instantly to match and _ => continue. So the loop run again and work but msg is change to "Error".

fn clear_terminal() {
    print!("{}c", 27 as char);
    stdout().flush().expect(ERR_MSG_STDOUT_FLUSH);
}

fn next(msg: &str) -> bool {
    let mut msg_new = msg;
    loop {
        clear_terminal();
    
        println!("The calculation end up with {}.", msg_new);
        print!("Do you want to make antoher calculation? (y/n): ");
        let mut next_string = String::new();
        stdout().flush().expect(ERR_MSG_STDOUT_FLUSH);
        stdin().read_line(&mut next_string).expect(ERR_MSG_STDIN_READ);
        match next_string.trim().parse() {
            Ok('y') => true,
            Ok('n') => false,
            _ => {
                msg_new = "Error";
                continue
            }
        };   
    }
}

Its problem with using print!() and stdout().flush()? I am totally new to rust. Thaks for every answer. OS: Windows 10, terminal: cmd (Command Promt)

CodePudding user response:

You must check whether a 'y' or a 'n' was entered at all, e.g. with a guard:

fn next(msg: &str) -> bool {
    let msg_new = msg;
    loop {
        clear_terminal();
    
        println!("The calculation end up with {}.", msg_new);
        print!("Do you want to make antoher calculation? (y/n): ");
        let mut next_string = String::new();
        stdout().flush().expect(ERR_MSG_STDOUT_FLUSH);
        match std::io::stdin().read_line(&mut next_string) {
            Ok(n) if n > 0 && next_string.chars().next().unwrap() == 'y' => break true,
            Ok(n) if n > 0 && next_string.chars().next().unwrap() == 'n' => break false,
            Ok(_) => {},  // other input is ignored
            Err(err) => panic_any(err),
        };
    }
}

Btw: next should be reserved for iterators

CodePudding user response:

When you enter y or n, the program does not go to the match arm with continue.

It sets the return value of the match statement to either true or false (which is never stored in a variable though) and then goes to the next iteration of the loop.

I guess you would actually like to return the boolean values from the next function in these match arms as shown below:

fn next(msg: &str) -> bool {
    let mut msg_new = msg;
    loop {
        clear_terminal();
    
        println!("The calculation end up with {}.", msg_new);
        print!("Do you want to make antoher calculation? (y/n): ");
        let mut next_string = String::new();
        stdout().flush().expect(ERR_MSG_STDOUT_FLUSH);
        stdin().read_line(&mut next_string).expect(ERR_MSG_STDIN_READ);
        match next_string.trim().parse() {
            Ok('y') => return true,
            Ok('n') => return false,
            _ => {
                msg_new = "Error";
                continue
            }
        };   
    }
}
  • Related