Io 是否有一种标准的方法来丢弃铁锈输入?

Io 是否有一种标准的方法来丢弃铁锈输入?,io,rust,stdin,Io,Rust,Stdin,从Rust中的stdin读取输入非常简单: use std::io; let mut some_string = String::new(); let _ = io::stdin().read_line(&mut some_string); 但有时您可能希望丢弃它,而不在任何地方确认它或获取缓冲区,例如: println!("Press Enter to close"); io::stdin().discard_input(); // discard_input() doesn't

从Rust中的
stdin
读取输入非常简单:

use std::io;

let mut some_string = String::new();
let _ = io::stdin().read_line(&mut some_string);
但有时您可能希望丢弃它,而不在任何地方确认它或获取缓冲区,例如:

println!("Press Enter to close");
io::stdin().discard_input(); // discard_input() doesn't exist

它可以读取任意数量的字符,直到遇到
\n
,忽略所有字符并不返回任何内容或
io::Result
。是否有一个标准的方法来实现它,或者我必须自己实现它?我跟踪了
read\u line
的实现,以
BufRead
实现,但我不确定从那里开始是否是一个好主意。

您可以在stdin上实现
。例如,在newline()之前丢弃\u

这应该是一个正确且高效的实现(使用缓冲区读取,但不将读取的部分复制到任何地方)。当然,如果您不需要任何长的行,只需一次读取一个字节,那么这可能会简单得多

use std::io::Stdin;
use std::io;
use std::io::prelude::*;

pub trait DiscardUntil {
    fn discard_until_newline(&mut self) -> Result<(), io::Error>;
}

impl DiscardUntil for Stdin {
    fn discard_until_newline(&mut self) -> Result<(), io::Error> {
        let mut buffered = self.lock();
        loop {
            let (consume, done) = {
                let data = try!(buffered.fill_buf());
                if data.is_empty() {
                    (0, true)
                } else if let Some(newline_pos) = data.iter().position(|b| *b == b'\n') {
                    (newline_pos + 1, true)
                } else {
                    (data.len(), false)
                }
            };
            buffered.consume(consume);
            if done {
                break;
            }
        }
        Ok(())
    }
}

fn main() {
    println!("hi");
    io::stdin().discard_until_newline().unwrap();
    println!("again");
    io::stdin().discard_until_newline().unwrap();
    println!("goodbye");
}
使用std::io::Stdin;
使用std::io;
使用std::io::prelude::*;
酒馆{
fn放弃,直到换行符(&mut self)->结果;
}
标准输入的输入丢弃{
fn放弃,直到换行符(&mut self)->结果{
让mut buffered=self.lock();
环路{
让(消费,完成){
让data=try!(buffered.fill_buf());
如果数据为空(){
(0,对)
}如果让某些(换行符位置)=data.iter().position(|b |*b==b'\n'),则为else{
(换行符位置+1,正确)
}否则{
(data.len(),false)
}
};
缓冲。消耗(消耗);
如果完成{
打破
}
}
好(())
}
}
fn main(){
println!(“hi”);
io::stdin()。在换行()之前丢弃。展开();
println!(“再次”);
io::stdin()。在换行()之前丢弃。展开();
println!(“再见”);
}

我尝试了bluss的代码,并能够提出一个性能稍差的实现,它不适合某些特殊情况(请参见下面的注释),但更简单、更简短:

use std::io;
use std::io::{Stdin, BufRead};

pub trait DiscardUntil {
    fn discard_until_newline(&mut self) -> Result<(), io::Error>;
}

impl DiscardUntil for Stdin {
    fn discard_until_newline(&mut self) -> Result<(), io::Error> {
        let mut buffered = self.lock();
        let amount = {
            let data = try!(buffered.fill_buf());
            data.len()
        };
        buffered.consume(amount);
        Ok(())
    }
}
使用std::io;
使用std::io::{Stdin,BufRead};
酒馆{
fn放弃,直到换行符(&mut self)->结果;
}
标准输入的输入丢弃{
fn放弃,直到换行符(&mut self)->结果{
让mut buffered=self.lock();
出租金额={
让data=try!(buffered.fill_buf());
data.len()
};
缓冲。消耗(数量);
好(())
}
}

我欢迎尝试设计一个更简单的解决方案。

仅使用
stdin
无法获得“按任意键继续”行为。例如,当使用终端时,您将无法读取用户在按下“回车”键之前键入的任何内容。回车限制适合我的需要。但是出于好奇,还需要什么来实现这一点呢?从Rust中的
stdin
读取也会读取按enter键生成的
\n
字符。所以你可以随时阅读一些东西。你应该把它编辑成你的问题,然后有人可以回答。关于评论中的问题:基本上是特定于平台的功能。需要的是一个合适的键盘API。标准库中没有任何内容,但有各种第三方库,例如当然,您也可以使用特定于平台的东西,比如winapi板条箱,或者任何与您的平台等效的东西。@LukasKalbertodt:例如,调用
libc
getchar()
,对吗?不过,我想要的是更简单的东西;我编辑了这个问题,你能详细解释一下吗?我在哪里冒险?如果我这样做会发生什么呢?当你消耗了所有的缓冲区,而没有检查是否有多行被读取到它。Fill buf将尝试填充整个缓冲区(通常为8K)。如果你这样做的话,你会发现你对方法的名称不真实。有没有办法触发它?当我测试它时,我不能。不能触发它并不意味着它不存在。我更喜欢编写构造正确的程序,而不是“看起来正确”。另一种情况是,当您消费少于一行时。因此,一种方法是插入8KB的数据,而不使用换行符。为了触发多行情况,我会尝试将多行文本粘贴到终端中。谢谢,我在回答中包含了这些信息。