简体   繁体   English

Read_line() 不等待用户循环输入。 Rust

[英]Read_line() don´t wait for users input in loop. Rust

What program shoud do?应该做什么程序?

  1. Read two numbers separated by space from terminal eg "10 8".从终端读取由空格分隔的两个数字,例如“10 8”。
  2. Split the string to Vec<&str> .将字符串拆分为Vec<&str>
  3. Parse Vec[0] and Vec[1] to num1 and num2 .Vec[0]Vec[1]解析为num1num2
  4. Read (math) operation from terminal and parse it.从终端读取(数学)运算并解析它。
  5. Print the "math" and result.打印“数学”和结果。 (10 * 80 = 80) (10 * 80 = 80)
  6. Catch almost every error in steps 2. - 4. and run try_again function.捕获步骤 2. - 4. 中的几乎所有错误,然后运行try_again function。
  7. If all goes right than run try_again function with "Success" msg如果一切顺利,请使用“成功” msg运行try_again function

(the main function is there only for context, the problem is in try_again function) main的 function 仅用于上下文,问题出在try_again函数中)

use std::io::{self, Write, Read, Error, ErrorKind};

const ERR_MSG_STDIN_READ: &str = "Problem with getting input";
const ERR_MSG_STDOUT_FLUSH: &str = "Problem with flushing stdout";

fn main() {
    loop {
        clear_terminal();

        print!("Write 2 ints separated by space: ");
        let mut nums_string = String::new();
        io::stdout().flush().expect(ERR_MSG_STDOUT_FLUSH);
        io::stdin().read_line(&mut nums_string).expect(ERR_MSG_STDIN_READ);
        let nums_str_vec: Vec<&str> = nums_string.trim()
.split(' ').collect();
        let num1: i32 = match nums_str_vec[0].parse() {
            Ok(num) => num,
            Err(_) => match try_again("Error") {
                true => continue,
                false => break
            }
        };
        let num2: i32 = match nums_str_vec[1].parse() {
            Ok(num) => num,
            Err(_) => match try_again("Error") {
                true => continue,
                false => break
            }
        };

        print!("Write one of these[+,-,*,/] maths operation for 2 inputed ints: ");
        let mut operation_string = String::new();
        io::stdout().flush().expect(ERR_MSG_STDOUT_FLUSH);
        io::stdin().read_line(&mut operation_string).expect(ERR_MSG_STDIN_READ);
        let operation = match operation_string.trim().parse() {
            Ok(char) => char,
            Err(_) => match try_again("Error") {
                true => continue,
                false => break
            }
        };
        match operation {
            '+' => println!("{} {} {} = {}", num1, operation, num2, num1 + num2),
            '-' => println!("{} {} {} = {}", num1, operation, num2, num1 - num2),
            '*' => println!("{} {} {} = {}", num1, operation, num2, num1 * num2),
            '/' => println!("{} {} {} = {} ({})", num1, operation, num2, num1 / num2, num1 % num2),
            _ => match try_again("Error") {
                true => continue,
                false => break
            }
        }
        io::stdin().read(&mut [0]).expect(ERR_MSG_STDIN_READ);
        match try_again("Success") {
            true => continue,
            false => break
        }
    }
}

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

What try_again function shoud do? try_again function 应该做什么?

  1. Save msg to msg_new for later changing.msg保存到msg_new以供以后更改。
  2. Read (y/n) answer from terminal and parse it.从终端读取 (y/n) 答案并解析它。
  3. If 'y' return true if 'n' return false .如果 'y' 返回true如果 'n' 返回false
  4. Catch almost every error in step 2. and continue "self loop" again.捕获步骤 2 中的几乎所有错误,然后再次继续“自循环”。 (With "Error" msg ) (带有“错误” msg
  5. The program (in main function) match returned result of try_again function => true means continue main loop, false means break the loop and end the program.程序(在main函数中)匹配try_again的返回结果try_again => true表示继续主循环,false表示跳出循环并结束程序。
fn try_again(msg: &str) -> bool {
    let mut msg_new = msg;
    loop {
        println!("The calculation end up with {}.", msg_new);
        print!("Do you want to make antoher calculation? (y/n): ");
        let mut answer_string = String::new();
        stdout().flush().expect(ERR_MSG_STDOUT_FLUSH);
        stdin().read_line(&mut answer_string).expect(ERR_MSG_STDIN_READ);
        match answer_string.trim().chars().next() {
            Some('y') => true,
            Some('n') => false,
            _ => {
                msg_new = "Error";
                continue
            }
        };  
    }
}

Whats the problem?有什么问题?

What doesn´t work in program?什么在程序中不起作用?

step 7 (maybe we can say 6 and 7) the problem is in try_again function.第 7 步(也许我们可以说第 6 步和第 7 步)问题出在try_again function 中。

What doesn´t work in try_again function什么在try_again中不起作用 function

When the program run try_again("Success");当程序运行try_again("Success"); : :

  1. In the first loop stdin().read_line(&mut next_string) doesn´t wait for users input and immediately go to _ => arm.在第一个循环中, stdin().read_line(&mut next_string)不等待用户输入并立即将 go 转换为_ => arm。
  2. And continue "self loop" again (with "Error" msg )并再次继续“自循环”(带有“错误” msg
  3. In the second loop actually wait for input and work but with wrong msg .在第二个循环中实际上等待输入和工作但是错误的msg

Final question最后一个问题

Why the stdin().read_line(&mut next_string) wait for input in secodn round of loop?为什么stdin().read_line(&mut next_string)在第二轮循环中等待输入? How to solve it?如何解决? Thanks for every answer!感谢您的每一个回答!


I am totally new to rust, please explain everything what you write.我是rust的新手,请解释你写的所有内容。 OS: Windows 10, terminal: cmd (Command Promt)操作系统:Windows 10,终端:cmd(命令提示符)

You must check whether a 'y' or a 'n' was entered at all, eg with a guard:您必须检查是否输入了'y''n' ,例如,与守卫一起:

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顺便说一句: next应该为迭代器保留

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM