关于rust:为什么在打印之前会读取输入内容?

Why does this read input before printing?

我在一些基本的I / O方面遇到了问题。具体来说,在输入名称并点击Enter

之后,将在输出中写入文本"请输入您的名字"

1
2
3
4
5
6
7
8
9
10
11
12
13
use std::io;

fn main() {
    print!("Please enter your name:");

    let mut name = String::new();
    match io::stdin().read_line(&mut name) {
        Ok(_) => println!(""),
        Err(err) => println!("Could not parse input: {}", err)
    }

    println!("Hello, {}!", name.trim());
}

提供以下输出:

1
2
3
4
5
Compiling chat v0.1.0 (file:///home/marcus/dev/rust/chat)
  Running `target/debug/chat`
marcus
Please enter your name:
Hello, marcus!

我在哪里输入了第一个" marcus"。为什么在等待输入之前,程序不打印"请输入您的姓名"?

如果返回的ResultOk,是否可以"不执行任何操作"?在示例中,Ok()表示我已将输入保存为变量名称。那太棒了。但是在这种情况下,我该如何使用Ok() =>


Why won't the program print"Please enter your name" before waiting for input?

嗯,确实如此。只是出于性能原因,对标准输出进行了缓冲。写入已完成,但仅写入内存中。如果希望它实际显示给用户,则必须触发刷新。这可以通过编写换行符,也可以通过显式执行:

1
2
3
4
io::Write::flush(&mut io::stdout()).expect("flush failed!");

// If you"use" `io::Write`...
io::stdout().flush().expect("flush failed!");

Also, is it possible to"do nothing" if a returned Result is Ok?

好的。只是...什么都不做。

1
2
3
4
match io::stdin().read_line(&mut name) {
    Ok(_) => { /* nothing */ },
    Err(err) => println!("Could not parse input: {}", err)
}

此处的相关要求是,match中的所有分支必须具有相同的结果类型。在println!的情况下,结果为();除了一个空块(或另一个返回()的函数)之外,您还可以使用文字:

1
2
3
4
match io::stdin().read_line(&mut name) {
    Ok(_) => (),
    Err(err) => println!("Could not parse input: {}", err)
}


这在print!的文档中进行了说明。由于print!不会发出换行符,并且stdout是行缓冲的,因此您将看不到任何输出。您可以手动刷新标准输出:

1
2
3
4
use std::io::{self, Write};

print!("Please enter your name:");
io::stdout().flush();

对于第二个问题,您始终可以显式返回单位:

1
Ok(_) => (),

因此您的程序变为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use std::io::{self, Write};

fn main() {
    print!("Please enter your name:");
    io::stdout().flush();

    let mut name = String::new();
    match io::stdin().read_line(&mut name) {
        Ok(_) => (),
        Err(err) => println!("Could not parse input: {}", err)
    }

    println!("Hello, {}!", name.trim());
}

正如@Veedrac在其(现在已删除)注释中指出的那样,您可以在read_line的结果上使用if let expression代替match

1
2
3
if let Err(err) = io::stdin().read_line(&mut name) {
    println!("Could not parse input: {}", err)
}


1
2
3
4
5
6
7
use std::io::{self, Write};

fn main() {
    print!("Please enter your name:");
    let _ = io::stdout().flush();
    // your io code
}