Skip to content
AgileLogics
6 min read

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! — like println! but without the newline.
  • format! — returns the formatted text as a String.
  • 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-facing Display format 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);
}