Rust println! formatting: {}, {:?}, width and precision
A cheat sheet for Rust format strings: placeholders, inline {name} args, {:?}, {:.2}, padding and alignment, hex, binary and format!.
println!, print!, format!, eprintln! and write! all use the same format string syntax. Each {} is a placeholder filled by an argument.
Filling placeholders
fn main() {
let item = "potion";
let qty = 3;
println!("{} x {}", qty, item);
println!("{qty} x {item}");
println!("{0} and {0} again, then {1}", item, qty);
println!("{label}: {}", qty * 2, label = "doubled");
}
3 x potion
3 x potion
potion and potion again, then 3
doubled: 6
{qty} is an inline format argument: it captures the variable by name. It only accepts a plain name, not an expression, so {qty * 2} is an error; put expressions after the string.
The format spec cheat sheet
Everything after a : inside the braces controls how the value looks.
| Spec | Meaning | Example | Output |
|---|---|---|---|
{} |
Display, the user-facing form | {}, "hi" |
hi |
{:?} |
Debug, the programmer form | {:?}, "hi" |
"hi" |
{:#?} |
pretty Debug, one field per line | structs, vectors | |
{:.2} |
2 digits after the decimal point | 3.14159 |
3.14 |
{:8} |
minimum width 8 | 42 |
42 |
{:<8} {:^8} {:>8} |
left, center, right align | "ab" |
ab |
{:*^8} |
fill character *, centered |
"ab" |
***ab*** |
{:05} |
pad with zeros | 42 |
00042 |
{:+} |
always show the sign | 42 |
+42 |
{:x} {:X} {:#x} |
hexadecimal | 255 |
ff, FF, 0xff |
{:b} {:#010b} |
binary, padded | 5 |
101, 0b00000101 |
{:e} |
scientific notation | 1500.0 |
1.5e3 |
{:width$} |
width from a variable | width = 6 |
Numbers are right-aligned by default and text is left-aligned. Specs combine in a fixed order: fill and alignment, sign, #, 0, width, .precision, type. So {:>10.2} is "right-align in 10 columns with 2 decimals".
format!, eprintln! and write!
format!returns the text as aStringinstead of printing it.eprintln!prints to standard error, which is where error messages belong (they stay out of piped output).write!andwriteln!format into anything that implementsWrite, such as aStringor a file; you'll usewrite!when implementingDisplayfor your own types.
Common mistakes
Putting an expression inside the braces:
fn main() {
let x = 5;
println!("{x + 1}");
}
error: invalid format string: the `+` sign flag must appear after `:` in a format string
The message is misleading: rustc reads the + as a formatting flag (like the one in {:+}, which prints a + sign on positive numbers). The real fix is to move the calculation out of the braces: println!("{}", x + 1).
Printing your own struct with {} gives E0277, "Point doesn't implement std::fmt::Display". Add #[derive(Debug)] and use {:?}, or implement Display yourself.
A literal brace must be doubled: println!("{{}}") prints {}. A mismatch between placeholders and arguments (println!("{} {}", a)) is a compile error, not a runtime surprise.
Example
fn main() {
let rows = [("Ferris", 1250.5, 7), ("Corro", 980.25, 12), ("Gopher", 15.0, 3)];
println!("{:<8}|{:>10}|{:>5}", "name", "score", "games");
println!("{:-<8}+{:->10}+{:->5}", "", "", "");
for (name, score, games) in rows {
println!("{name:<8}|{score:>10.2}|{games:>5}");
}
let id = 42;
println!("ticket #{id:05}, hex {id:#x}, binary {id:#010b}");
println!("change: {:+}, {:+}", 7, -3);
let width = 12;
println!("[{:^width$}]", "centered");
let summary = format!("{} players", rows.len());
println!("{summary:?}");
}
Output:
name | score|games
--------+----------+-----
Ferris | 1250.50| 7
Corro | 980.25| 12
Gopher | 15.00| 3
ticket #00042, hex 0x2a, binary 0b00101010
change: +7, -3
[ centered ]
"3 players"