Rust Strings
Text in programming is called a string, as in a string of characters. Rust has two main kinds of string, and knowing the difference early will save you a lot of confusion later. Do not worry, the idea is simpler than it first sounds.
&str, pronounced "string slice", is a view of some text that already exists somewhere. Text you write in double quotes in your code, like"hello", is a&str. You can read it, but you cannot make it longer.Stringis text that your program owns and can change: add to it, shorten it, build it up piece by piece. Text the user types, or text you assemble while the program runs, usually lives in aString.
A handy picture: a String is a notebook you own and can write in. A &str is like pointing at a sentence in a book; you can read it, but it is not yours to change.
Creating and growing a String
fn main() {
let mut message = String::from("Hello");
message.push_str(", world");
message.push('!');
println!("{}", message);
println!("It has {} characters.", message.len());
}Hello, world! It has 13 characters.
String::from turns a &str into a String. push_str adds more text, and push adds a single char. Both need the variable to be mut.
Joining strings with format!
The friendliest way to combine several pieces into a new String is the format! macro. It works exactly like println!, but instead of printing, it gives you the finished text:
fn main() {
let first = "Ada";
let last = "Lovelace";
let full = format!("{} {}", first, last);
let badge = format!("Name: {} ({} letters)", full, full.len() - 1);
println!("{}", badge);
}Name: Ada Lovelace (11 letters)
You can also use +, as in let s = s1 + "text";, but it has a few surprising rules about ownership. format! never surprises you, which is why many Rust programmers prefer it.
Characters are not always one byte
len() counts bytes, not letters. For English text they are the same, but many characters, like é, ₹ or an emoji, take more than one byte. To count what a person would call characters, use .chars().count():
fn main() {
let word = "café";
println!("Bytes: {}", word.len());
println!("Characters: {}", word.chars().count());
for c in word.chars() {
print!("[{}]", c);
}
println!();
}Bytes: 5 Characters: 4 [c][a][f][é]
This is also why Rust does not let you write word[0] to get the first letter: with text from all over the world, the first byte might be only part of a character. Rust prefers to be safe rather than give you half a letter.
Practice exercises
- Start with an empty
String, add your first name, a space and your last name, and print it. - Use
format!to build the sentence "Today is Monday, 1 January" from three variables. - Count the bytes and the characters of the word "naïve" and explain the difference.