Skip to content
Select theme

How to format strings with println! and format!

Short answer: println! prints and format! returns a String, and both read the same format string: each {} takes one value — by position ({} or {1}), straight from a variable in scope ({name}), or by a name you pass (name = value) — and the spec after the colon ({:?}, {:>8}, {:.2}) decides how that value prints.

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

Ada Lovelace
Lovelace, Ada and Lovelace again

Bare {}s take the arguments in order. Number them and any argument can be reused or reordered — {1}, {0} prints the second one first. The values are borrowed, not consumed, so first and last are still there afterwards.

Ada was born in 1843

Name a variable inside the braces and the macro reads it straight from scope — no argument list at all. A {} naming something that doesn’t exist is an ordinary “cannot find value” error, because the capture really is the variable, not a key looked up at runtime. Building a string from parts uses this spelling already.

Lovelace, Ada

Named arguments sit after the format string as name = value pairs, so the order in the braces is free, and the name doesn’t have to match any variable — sum = a + b is fine, since the value is any expression. format! is the same syntax with a different job: it returns the String instead of printing it.

{} asks for Display, the formatting for finished human-facing text, and not every type has it. A Vec doesn’t:

error[E0277]: `Vec<{integer}>` doesn't implement `std::fmt::Display`
--> src/main.rs:3:20
|
3 | println!("{}", numbers);
| -- ^^^^^^^ `Vec<{integer}>` cannot be formatted with the default formatter
| |
| required by this formatting parameter
|
= help: the trait `std::fmt::Display` is not implemented for `Vec<{integer}>`
= note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead
For more information about this error, try `rustc --explain E0277`.

{:?} asks for Debug instead, and {:#?} prints it pretty:

[1, 2, 3]
[
1,
2,
3,
]

Everything after the colon is a spec for how the value prints:

[ Ada]
[Ada ]
[ Ada ]
01843
3.14
2.000
{ and }

> right-aligns, < left-aligns, ^ centres — the odd space goes right — and the number is the minimum width, padded with spaces or with a leading 0. .2 is precision: two digits after the point for a float, rounded and zero-padded (1.99999 prints as 2.000), and a hard cut at two characters for a string. Doubled braces print one literal brace.

print! without the trailing newline — and the flush that makes its output appear — plus eprintln! for standard error, each have their own page later in this chapter.