Printing & Formatting
Prerequisites: Operators
println! and its relatives take a format string with {}
placeholders, followed by the values to fill them with. Because they
are macros, the format string is checked at compile time — a
mismatched number of arguments is a compile error, not a runtime bug.
Syntax
println!("{}", value); // Display: user-facing output
println!("{value}"); // inline: the variable named `value`
println!("{:?}", value); // Debug: developer-facing output
println!("{:#?}", value); // pretty Debug, spread over lines
println!("{:.2}", 1.23456); // 2 decimal places
println!("{:>8}", "hi"); // right-align in 8 columns
let text = format!("{}!", value); // build a String instead of printing
eprintln!("oops"); // print to standard error
The most useful format specs:
| Spec | Meaning |
|---|---|
{} |
Display formatting |
{:?} |
Debug formatting (arrays, quotes, …) |
{:#?} |
pretty-printed Debug |
{:.2} |
2 digits after the decimal point |
{:>8} |
right-align in a field 8 wide |
{:<8} |
left-align |
{:^8} |
center |
{:08.2} |
pad with zeros, width 8, 2 decimals |
{0} {1} |
positional arguments, reusable |
Specs work with inline names too: {score:.2}, {name:>8}. Inline
names can only be plain variable names — for an expression such as
a + b, use {} and pass it as an argument.
print!— likeprintln!but without the newline.format!— returns the formatted text as aString.eprintln!/eprint!— write to standard error, the stream for error messages. It still appears in the terminal, but stays separate if standard output is redirected to a file.{{and}}— print a literal{or}.
Example
fn main() {
let name = "Ada";
let score = 93.456;
let items = [1, 2, 3];
println!("Hello, {}!", name);
println!("Hello, {name}!");
println!("{0} scored {1}. Well done, {0}!", name, score);
println!("Score: {score:.2}");
println!("[{:>8}]", name);
println!("[{:<8}]", name);
println!("[{:^8}]", name);
println!("[{:08.2}]", score);
println!("{:?}", items);
println!("{:?}", name);
println!("{:#?}", items);
let message = format!("{name} scored {score:.1}");
println!("{message}");
println!("{{braces}}");
eprintln!("This line goes to standard error");
}
Expected output
Hello, Ada!
Hello, Ada!
Ada scored 93.456. Well done, Ada!
Score: 93.46
[ Ada]
[Ada ]
[ Ada ]
[00093.46]
[1, 2, 3]
"Ada"
[
1,
2,
3,
]
Ada scored 93.5
{braces}
This line goes to standard error
Common mistakes
- Placeholder and argument counts don't match.
println!("{} {}", a);fails at compile time:
error: 2 positional arguments in format string, but there is 1 argument
- Printing an array (or your own type) with
{}. Only types with a user-facingDisplayformat support{}:
error[E0277]: `[{integer}; 3]` doesn't implement `std::fmt::Display`
Use {:?} instead — the compiler's note suggests exactly that.
- Writing an expression inline, like
{a + b}. Inline arguments only accept names; pass expressions as separate arguments.
Practice
Print a small receipt where item names are left-aligned in 8 columns and prices are right-aligned in 8 columns with 2 decimals:
Coffee 3.50
Bagel 2.25
Total 5.75
Show solution
fn main() {
let coffee = 3.5;
let bagel = 2.25;
println!("{:<8}{:>8.2}", "Coffee", coffee);
println!("{:<8}{:>8.2}", "Bagel", bagel);
println!("{:<8}{:>8.2}", "Total", coffee + bagel);
}