84

The macro println! in Rust always leaves a newline character at the end of each output. For example

println!("Enter the number : ");
io::stdin().read_line(&mut num);

gives the output

Enter the number : 
56

I don't want the user's input 56 to be on a new line. How do I do this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
7_R3X
  • 3,904
  • 4
  • 25
  • 43
  • Does this answer your question? [Why does this read input before printing?](https://stackoverflow.com/questions/34993744/why-does-this-read-input-before-printing) – lmat - Reinstate Monica Jan 06 '23 at 11:04

4 Answers4

138

It's trickier than it would seem at first glance. Other answers mention the print! macro but it's not quite that simple. You'll likely need to flush stdout, as it may not be written to the screen immediately. flush() is a trait method that is part of std::io::Write so that needs to be in scope for it to work (this is a pretty easy early mistake).

use std::io;
use std::io::Write; // <--- bring flush() into scope


fn main() {
    println!("I'm picking a number between 1 and 100...");

    print!("Enter a number: ");
    io::stdout().flush().unwrap();
    let mut val = String::new();

    io::stdin().read_line(&mut val)
        .expect("Error getting guess");

    println!("You entered {}", val);
}
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
Induane
  • 1,774
  • 2
  • 13
  • 11
  • 1
    This is the right answer! Thanks a lot for your help! – enbermudas Mar 05 '20 at 12:37
  • 2
    As this is a common "early mistake," it's worth pointing out that the addition of unwrap() after flush() is to implicitly handle any errors with the flush. I.E. one could also do: `io::stdout().flush().expect("flush failed.");` – robotshapes Jun 27 '22 at 15:34
64

You can use the print! macro instead.

print!("Enter the number : ");
io::stdin().read_line(&mut num);

Beware:

Note that stdout is frequently line-buffered by default so it may be necessary to use io::stdout().flush() to ensure the output is emitted immediately.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
sjagr
  • 15,983
  • 5
  • 40
  • 67
  • 32
    "*Note that stdout is frequently line-buffered by default so it may be necessary to use `io::stdout().flush()` to ensure the output is emitted immediately.*" - https://doc.rust-lang.org/std/macro.print!.html – ArtemGr May 30 '16 at 20:51
  • @ArtemGr: In C++ (and C I think), when you attempt to read from `stdin`, the `stdout` buffer is immediately flushed. I would have expected (maybe wrongly) the same behavior from Rust, and the example presented on the `print!` page does not read from `stdin` so it's inconclusive in this regard... do you have more information? – Matthieu M. May 31 '16 at 07:57
  • @MatthieuM. I did a simple test on Windows and Linux with Rust nightly and there is **no stdout flush** happening in the answer's code, e.g. "Enter the number : " is printed only **after the program ends** and not before the `read_line` happens. – ArtemGr May 31 '16 at 09:49
  • @ArtemGr: Ouch... that's quite confusing! It may be argued it's better in a way (explicit is better than implicit) but it makes it really necessary to flush then! – Matthieu M. May 31 '16 at 11:21
  • 1
    @MatthieuM. Yeah, I like it that the standard input and output are not affecting each other in Rust. Flushing the output on input sounds like a nasty side effect to me. – ArtemGr May 31 '16 at 11:24
  • @ArtemGr: It can pretty confusing and having to use `std::cin::tie(0)` to deactivate it is not easily discoverable; on the other hand I guess it makes sense for small interactive binaries, similarly to the case here, when waiting for an answer you better make sure the question was displayed :) I think it's one of those "prototypes made easy" decision that comes and bites you at scale. – Matthieu M. May 31 '16 at 11:30
  • @MatthieuM. Perhaps adding a flush to `print!` is a good idea (https://github.com/rust-lang/rust/issues/23818). It would also be neat to have a flushing escape ("foo\fbar\f"), but that's just me dreaming. – ArtemGr May 31 '16 at 11:46
0

Don't use the print/ln!-macros. Use write/ln!-macros.
It is more verbose, but print/ln! are problematic for using in command-line apps where their output might get piped or redirected to other apps, which is characteristic for Unix environments.
There is used always the same (only once requested and "buffered") stdout-device, but the stdout-device of the system is changed for piping/redirecting. So for each output to stdout you have to request the current stdout-device (std::io::stdout()). This can be done with write/ln!-macros.
So to say print/ln! is broken and there is an open issue since years.

Markus
  • 512
  • 1
  • 4
  • 21
0

The '56' is displayed on the next line because the read_line function also reads the newline character \n that the user enters after typing their input. The println! macro then adds another newline character at the end of the output, which causes the value to be displayed on a new line.

To display '56' on the same line, you can use the trim() method to remove the newline character from the end of the input before printing it.

input = input.trim().to_string();