Skip to content
Select theme

How to print without a trailing newline

Short answer: print! is println! without the newline: same format string, nothing added at the end. When the text has to be on screen before the program does anything else, follow it with std::io::stdout().flush(). Stdout is buffered, and a print! with no newline in it can sit in that buffer until the next newline or the end of the program.

From a fresh project — cargo new string-demo, then replace src/main.rs with each block below and run it with cargo run. The project name doesn’t matter; nothing in the output depends on it.

Hello, Ada!

Two print!s land on one line, and whatever prints next continues it. The format string is the same one println! takes — the format mini-language is shared. A program that ends on a print! leaves the line unfinished, and the shell’s next prompt appears right after the text.

Print without a newline in a loop and the timing shows:

1 2 3 4 5 done

Run it and watch: two and a half seconds of nothing, then the whole line at once. Nothing was lost. Stdout is line-buffered: the buffer is written out when a newline goes into it, when you flush it yourself, or when the process exits. No print! above contains a newline, so all five numbers wait for the println!("done"). The same buffering keeps a print!("Name: ") before reading input off the screen until the input arrives: the prompt waits in the buffer while the program waits for the keyboard.

The two streams side by side make the buffer visible. This writes to stdout, then to standard error, then to stdout again:

In a terminal both streams go to the same screen, and the middle write is the first thing on it:

unbuffered
buffered line

Standard error isn’t held in stdout’s buffer, so its line is out while the print! text is still waiting. (eprintln! has its own article, next in this chapter.)

Two more lines and the numbers stream out as they are computed:

1 2 3 4 5 done

use std::io::Write puts flush in scope; it’s a method on the Write trait, the same one print! writes through. stdout().flush() pushes the buffer out now. It returns an io::Result<()> because a flush is a write, and writes fail: pipe the output into head and the writes eventually fail with a broken pipe. print! panics on that (failed printing to stdout: Broken pipe (os error 32)); flush() hands the error to you instead, and the unwrap() here panics on it too.

Two cases where a plain print! is fine. The text ends with a newline (println!, or print!("{i}\n")), because the newline itself flushes the buffer. Or the program ends right after, since the buffer is flushed at exit. That’s why the late prompt eventually appeared. What the flush buys is output that shows up while the program is still running.