print! macro gets executed out of order [duplicate]

倾然丶 夕夏残阳落幕 提交于 2019-12-20 03:07:06

问题


A portion of my code looks like this:

print_usage_instructions();
print!("Command: ");
let stdin = io::stdin();
let mut line = String::new();
stdin.lock().read_line(&mut line).expect("Couldn't process the command.");
println!("{}", line);

The behaviour I expect here is something like this:

Usage instructions and stuff
Command: [my command]
[my command]

However, what happens is this:

Usage instructions and stuff
[my command]
Command: [my command]

Any ideas why would that happen? AFAIK, there's no reason for the compiler to change the execution order here, this part of the code is not async nor multithreaded.


回答1:


The problem: print!() doesn't flush stdout!

What does flushing mean, you ask? When printing, you don't want to send every character to stdout on its own: this would occur a lot of overhead (think: doing a syscall, the terminal would have to update its view, ...). So instead of doing that, there is exists a buffer somewhere which holds the content which is about to be printed. To actually print, this buffer has to be flushed.

The reason you hardly notice all of this is, that stdout is always flushed when a newline ('\n') is printed. Thus, println!() always flushes!

Your use case is even more confusing, because you are typing into stdin. Here it works pretty much the same way: when you type, the characters are not yet send anywhere! Only the terminal/shell stores what you typed. But once you hit enter (newline), your written text is submitted and send to stdin.

Anyway, you can manually flush stdout without printing a newline:

use std::io::{self, BufRead, Write};

fn main() {
    println!("Usage instructions and stuff");

    print!("Command:");
    io::stdout().flush().expect("Couldn't flush stdout");   // <-- here

    let stdin = io::stdin();
    let mut line = String::new();
    stdin.lock().read_line(&mut line).expect("Couldn't process the command.");
    println!("{}", line);
}

This behavior was criticized before: "print! should flush stdout".


And please note: your string line contains a newline character at the very end. You can remove it with trim_right(). This has nothing to do with your original question, but you are likely to run into this problem as well ;-)



来源:https://stackoverflow.com/questions/49607156/print-macro-gets-executed-out-of-order

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!