1.5Introduction to println! and formatting
You've been using println! since your first program. This lesson makes you fluent in it, which is worth doing early: printing is how your programs will talk to you for the entire course, including when you're hunting bugs (chapter 3 turns it into a debugging technique).
println! and print!
println! writes its text to the screen and then ends the line, so the next print starts on a fresh one. Its sibling print! writes the text and stays put:
fn main() {
print!("One. ");
print!("Two. ");
println!("Three.");
println!("Four.");
}One. Two. Three.
Four.
The three pieces printed with print! and println! ended up on one line; only println! moved on. Most of the time println! is what you want, with one wrinkle worth knowing now: terminals are allowed to hold back an unfinished line, so text from a bare print! may not appear on screen until something ends the line. We'll dodge that wrinkle in the next lesson and dissolve it properly in chapter 20.
Placeholders
To mix values into the text, use {} as a placeholder, then supply the values as extra arguments, in order:
fn main() {
let a = 6;
let b = 4;
println!("{} plus {} is {}", a, b, a + b);
}6 plus 4 is 10
Each {} is filled by the next argument. And note the third argument: a + b is a calculation, not a variable. Any expression that produces a printable value works as an argument; the math happens first, then the result is printed.
When the value you're printing is a single variable, there's a shortcut you've already been using: put the name right inside the braces.
fn main() {
let score = 250;
println!("score: {score}");
}score: 250
The inline form only accepts a plain variable name. {a + b} doesn't compile; calculations have to go the {}-plus-argument route. A good habit that keeps both rules easy to remember: braces hold a name or nothing.
Best practice
Prefer the inline form ({score}) when printing a variable: the text reads like the output it produces, and there's no counting-arguments gymnastics. Use empty {} with arguments when printing computed values.
Two more placeholder tricks complete the set. Placeholders can be numbered to reuse or reorder arguments ({0} is the first argument, {1} the second):
fn main() {
println!("{0}, {1}! {0}!", "Go", "team");
}Go, team! Go!
And arguments can be given names, which read nicely when there are several:
fn main() {
println!("{name} scored {points} points", name = "Ada", points = 250);
}Ada scored 250 points
You'll see all three styles in real code; inline names dominate modern Rust.
Escape sequences
Some characters can't be typed into a string literally, so they're written as escape sequences: a backslash plus a code. The ones you'll actually use:
\nstarts a new line ("newline").println!effectively adds one of these for you at the end;print!doesn't.\tinserts a tab, handy for rough columns.\"puts a double quote inside a double-quoted string.\\prints an actual backslash, since a lone one would start an escape.
And one non-backslash escape, because braces have a job now: to print a literal { or }, double it ({{ and }}).
fn main() {
println!("line one\nline two");
println!("name:\tAda");
println!("she said \"hello\"");
println!("C:\\projects");
println!("braces look like {{}}");
}line one
line two
name: Ada
she said "hello"
C:\projects
braces look like {}
A \n in the middle of a string is also a tidy way to print two lines with one statement, which you'll see in examples from here on.
Quiz time
Question #1
What does this program print?
fn main() {
print!("a");
println!("b\nc");
println!("d");
}Show solution
ab
c
d
The print! leaves the cursor after a, so b lands on the same line; the \n ends that line and starts the one holding c; the println! ends it; d gets its own line.
Question #2
What does this program print?
fn main() {
let x = 3;
println!("{0} times {1} is {2}, and {1} times {0} is also {2}", x, 5, x * 5);
}Show solution
3 times 5 is 15, and 5 times 3 is also 15
{0} is x (3), {1} is 5, and {2} is the computed x * 5. Numbered placeholders can repeat and reorder freely.
Question #3
Predict the compiler error: what's wrong here?
fn main() {
println!("the answer is {}");
}Show solution
The format string has one {} placeholder but no argument to fill it, and the program doesn't compile. The compiler says exactly that: "1 positional argument in format string, but no arguments were given", pointing at the braces. (This check happening at compile time is quietly remarkable; in C, the equivalent mistake compiles and misbehaves at runtime.)
You can now talk to the user. Next lesson, the conversation goes both ways: reading what they type back.