Skip to content

Step 1 of 5 · Reading · ~3 min

Learn

Strings

Formatting

By the end of this lesson you can control exactly how a value is printed: how many decimals, how wide the column is, which side it hugs, and what fills the gap. Every exercise in this course is graded byte for byte, so this is the skill that turns "looks right" into "passes".

Placeholders and the format spec

A {} in println! is a placeholder: it is replaced by the next argument, using the type's Display rendering (the human-facing one). Anything you put after a colon inside the braces is the format spec, a small language that says how to render that one value:

let city = "Oslo";
let temp = 3.14159;
println!("{} is {}", city, temp);    // Oslo is 3.14159
println!("{} is {:.1}", city, temp); // Oslo is 3.1

The format string is checked at compile time: one {} too many or too few is a build error, not garbled output. Named placeholders such as {city} that pull a variable from scope need Rust 1.58+, and this course's grader is older, so always pass values as arguments. For collections, {:?} uses Debug formatting instead: println!("{:?}", vec![1, 2]) prints [1, 2].

Precision: {:.N}

.N means "exactly N digits after the decimal point". It rounds to the nearest value and it adds zeros when the number has fewer digits:

println!("{:.2}", 9.5);     // 9.50   (zeros added)
println!("{:.2}", 0.4567);  // 0.46   (rounded up, not cut to 0.45)
println!("{:.1}", 7.96);    // 8.0    (rounding can carry into the integer part)
println!("{}", 9.5);        // 9.5    (plain {} never pads with zeros)

Width, alignment and fill

A number before the precision is the width: the minimum number of characters the value occupies. Shorter values are padded with spaces; longer values are printed in full, never cut. The alignment character goes before the width: < left, > right, ^ center.

The default side depends on the type, and this is the trap: strings default to left, numbers default to right.

println!("|{:6}|", "tea");      // |tea   |    string: left by default
println!("|{:6}|", 42);         // |    42|    number: right by default
println!("|{:>6}|", "tea");     // |   tea|    forced right
println!("|{:^7}|", "tea");     // |  tea  |    centered
println!("|{:4}|", "espresso"); // |espresso|  too long: printed whole

A 0 right before the width pads a number with leading zeros instead of spaces:

println!("#{:05}", 318);    // #00318
println!("#{:5}", 318);     // #  318   same width, spaces
println!("#{:05}", 123456); // #123456  already wider than 5: untouched

Putting specs together

Here is a small receipt line that uses all three on different values:

let item = "mug";
let qty = 4;
let unit = 3.5;
println!("{:<8}x{:>3} = {:>7.2}", item, qty, unit * qty as f64);
// mug     x  4 =   14.00

{:>7.2} reads as: right-aligned, width 7, two decimals. The order inside the braces is always alignment, then 0, then width, then .precision. The same spec language works in print!, format! (which returns a String instead of printing) and eprintln! (which writes to stderr, so debug output there never breaks graded stdout).

Common mistakes

  • Plain {} on a float. 1.5 prints as 1.5, not 1.50; only a precision like {:.2} adds the missing zero.
  • Width without the 0. {:3} on 7 prints 7 (two spaces), not 007. The zero flag is what makes the padding digits.
  • Forcing the wrong side on a string. {:>8} right-aligns, so ab becomes ab; a text column that should hug the left needs < or no alignment character at all.
  • Truncating instead of rounding. Converting to an integer to cut decimals turns 2.678 into 2.67; {:.2} gives the correct 2.68.

Your exercise

Print a three-line name badge using width, zero padding and precision. The starter reads the name, age and height and prints them with bare {}, so every line is wrong until you add the right format specs. Watch the padded name column and the rounding of the height.

Up nextIf Expressions and matchControl Flow

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…