Распечатать! макрос выполняется не в порядке

Часть моего кода выглядит так:

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);

Поведение, которое я ожидаю здесь, выглядит примерно так:

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

Однако, что происходит, это:

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

Есть идеи, почему это случилось? AFAIK, у компилятора нет причин менять здесь порядок выполнения, эта часть кода не асинхронная и не многопоточная.

1 ответ

Решение

Эта проблема: print!() не сбрасывает стандартный вывод!

Вы спрашиваете, что означает промывка? При печати вы не хотите отправлять каждый символ в stdout самостоятельно: это может привести к большим накладным расходам (подумайте: при выполнении системного вызова терминал должен будет обновить свое представление, ...). Таким образом, вместо того, чтобы сделать это, существует где-то буфер, который содержит содержимое, которое должно быть напечатано. Чтобы на самом деле печатать, этот буфер должен быть очищен.

Причина, по которой вы едва замечаете все это, в том, что stdout всегда сбрасывается при переводе строки ('\n') печатается. Таким образом, println!() всегда вспыхивает!

Ваш вариант использования еще более запутанный, потому что вы вводите в stdin. Здесь все работает примерно так же: когда вы печатаете, символы еще никуда не отправляются! Только терминал / оболочка хранит то, что вы набрали. Но как только вы нажмете клавишу ввода (перевод строки), ваш письменный текст будет отправлен и отправлен на стандартный ввод.

В любом случае, вы можете вручную сбросить стандартный вывод без печати новой строки:

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);
}

Такое поведение было подвергнуто критике раньше: print! должен смывать стандартный вывод ".


И, пожалуйста, обратите внимание: ваша строка line содержит символ новой строки в самом конце. Вы можете удалить это с trim_right(), Это не имеет ничего общего с вашим первоначальным вопросом, но вы, скорее всего, столкнетесь и с этой проблемой;-)

Другие вопросы по тегам