Step 3 of 6
Joining text: format! and +
format!: println! that returns the text
format! takes the same format string and values as println! (with {}, {name}, {:.2} and {:?}), but instead of printing, it returns the result as a new String:
fn main() {
let name = "Ana";
let visits = 3;
let msg = format!("Welcome back, {name}! Visit #{visits}");
let price = format!("{:.2} EUR", 7.5);
println!("{msg}");
println!("{price}");
}
Welcome back, Ana! Visit #3
7.50 EUR
Use it whenever you need text built from values: messages, file names, IDs, report lines. It's the most common way to build strings in Rust.
Joining with +
You can also join strings with +:
fn main() {
let first = String::from("Ada");
let last = String::from("Lovelace");
let full = first + " " + &last;
println!("{full}");
println!("{last}");
}
Ada Lovelace
Lovelace
+ has two rules that surprise everyone at first:
- The left side must be a
Stringand the right side a&str." "is a literal, so it's already a&str. For theStringlast, write&last: the&passes a view of its text instead of theStringitself. You'll use the same trick anywhere a&stris expected and you have aString, for examples.push_str(&other). +reuses the leftString's memory and takes it over. Afterfirst + ..., the variablefirstcan't be used anymore (laststill can, because&only lent it). Usingfirstafterwards is error E0382,borrow of moved value: `first`. Module 09 explains these moves properly.
Because of those rules, many Rust programmers prefer format!("{first} {last}"): it reads like the result, and it leaves every variable usable.
Appending with +=
s += "text"; appends to s in place, just like s.push_str("text"). With a String on the right, add & again: s += &other;.
Common mistakes
- Adding two Strings. The right side must be a
&str:
fn main() {
let a = String::from("Hello, ");
let b = String::from("world");
let c = a + b;
println!("{c}");
}
error[E0308]: mismatched types
The message says expected `&str`, found `String` and suggests &b ("consider borrowing here"). Or write format!("{a}{b}").
- Using the left variable after
+: see the move rule above. If you still need it, useformat!.
Your task
Write greeting(name, visits). On the first visit (visits is 1) it returns Welcome, Ana!; on later visits it returns Welcome back, Ana! Visit #3 (with the real name and number).
Challenge 2
Write price_tag(item, cents), which returns text like coffee: $3.50. Prices are stored in whole cents, so price_tag("coffee", 350) returns "coffee: $3.50". Always show two decimals.
Challenge 3
Write countdown(n), which returns the numbers from n down to 1, separated by spaces, followed by liftoff!. For example countdown(3) returns "3 2 1 liftoff!" and countdown(0) returns "liftoff!".
Previous: Growing a String with push_str and push Next: Length: bytes versus characters