【问题标题】:How to clear or remove io::stdin buffer in Rust?如何清除或删除 Rust 中的 io::stdin 缓冲区?
【发布时间】:2021-06-29 18:00:27
【问题描述】:

在开始学习 Rust 语言后,我一直在用 Rust 编写一个简单的基于文本的游戏,并且我尝试实现一个函数来等待用户在继续程序之前按下 enter。

到目前为止,经过一些实验,我已经做到了:

pub fn wait() {
    let mut stdin = io::stdin();
    let wait_string = &mut String::new();

    wait_string.clear();
    println!("\nPress Enter to Continue\n");
    io::stdout().clear();
    stdin.read_line(wait_string);
}

但是,我的问题是,由于标准输入上的硬编码缓冲区,如果用户在显示消息之前按下回车,该函数将自动继续运行而无需等待。

有解决办法吗?或者使用 std::thread::sleep 的另一种方法会更好吗? 如果这很容易解决或不可能解决,我深表歉意,我仍在 Rust 中找到自己的立足点。

【问题讨论】:

    标签: rust


    【解决方案1】:

    您可以暂时切换到底层文件描述符上的非阻塞操作,以消耗在此 wait() 调用之前可能已输入的所有内容,然后切换回阻塞操作以实际等待输入。

    此示例需要libc crate,并且仅适用于 Unix(我猜想在 Windows 上可以使用winapi crate 完成类似的操作)。

    pub fn change_blocking_fd(
        fd: std::os::unix::io::RawFd,
        blocking: bool,
    ) {
        unsafe {
            let flags = libc::fcntl(fd, libc::F_GETFL);
            libc::fcntl(
                fd,
                libc::F_SETFL,
                if blocking {
                    flags & !libc::O_NONBLOCK
                } else {
                    flags | libc::O_NONBLOCK
                },
            );
        }
    }
    
    pub fn wait() {
        use std::os::unix::io::AsRawFd;
        let stdin = std::io::stdin();
        change_blocking_fd(stdin.as_raw_fd(), false);
        let mut wait_string = String::new();
        while stdin.read_line(&mut wait_string).is_ok() {
            println!("discard: {:?}", wait_string); // debug purpose only
            wait_string.clear();
        }
        change_blocking_fd(stdin.as_raw_fd(), true);
        println!("\nPress Enter to Continue\n");
        stdin.read_line(&mut wait_string).expect("!!!");
    }
    
    fn main() {
        println!("enter a few lines during five seconds");
        std::thread::sleep(std::time::Duration::from_millis(5000));
        println!("~~~~ before wait() ~~~~");
        wait();
        println!("~~~~ after wait() ~~~~");
    }
    /*
    enter a few lines during five seconds
    aaa
    zzz
    eee
    ~~~~ before wait() ~~~~
    discard: "aaa\n"
    discard: "zzz\n"
    discard: "eee\n"
    
    Press Enter to Continue
    
    
    ~~~~ after wait() ~~~~
    */
    

    【讨论】:

      猜你喜欢
      • 2014-01-15
      • 1970-01-01
      • 2020-04-11
      • 2020-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      相关资源
      最近更新 更多