Rust — Strings
Two string types (yes, both matter)
| Type | Kind | Where it lives | Mutable? |
|---|---|---|---|
String | owned, growable | heap | yes |
&str ("string slice") | borrowed view | anywhere (heap/static) | read-only |
let owned = String::from("grow me"); // heap-allocated, editable
let slice = "I am a &str"; // baked into the binary
Rule of thumb: use &str in function parameters and struct fields; use String when you must own or build.
Creating Strings
let s1 = String::from("hello");
let s2 = "hello".to_string();
let s3 = String::new(); // empty, grows later
let s4: &str = "slice";
All four hold valid UTF-8 text.
Building — push and format!
let mut s = String::from("Hello");
s.push_str(", world"); // append string
s.push('!'); // append single char
// idiomatic composition:
let full = format!("{} {}", "Ada", "Lovelace");
format! is usually cleanest — it takes {} placeholders like println! and returns an owned String without touching its inputs.
Concatenation quirks
let a = String::from("Hello, ");
let b = "world";
let c = a + b; // moves `a`! a is gone now
println!("{}", c); // "Hello, world"
let d = "Hello, ".to_string() + b; // keep original by cloning/to_string first
+ uses addition that takes ownership of the left side. format! avoids all such surprises:
let out = format!("{}{}", "Hello, ", "world");
Indexing is forbidden — for good reason
let s = String::from("hello");
// s[0] ❌ compile error!
Rust strings are UTF-8 byte arrays; s[0] would be ambiguous (byte? char?). Iterate or slice explicitly instead:
for ch in "héllo".chars() {
println!("{}", ch); // h é l l o — real characters
}
let hello = &s[0..5]; // SLICE — must land on char boundaries
.len() returns bytes, not letters: "héllo".len() is 6 (é is two bytes). Use .chars().count() for visible length.
Everyday methods
let s = String::from(" Hello, Rust ");
s.trim(); // "Hello, Rust" strip whitespace
s.to_uppercase(); // case transforms → new String
s.contains("Rust"); // true
s.replace("Rust", "World"); // substituted copy
s.split(", "); // iterator of pieces
s.starts_with(" Hello"); // prefix test
All return new values — originals untouched (immutability rules apply to Strings too unless mut).
Mini Practice
- Build a full name from first + last via format!.
- Prove
"héllo".len()≠ character count; fix with chars().count(). - Trim + lowercase user input before comparing to "yes".
- Split "a,b,c" and print each piece on its own line.
- Demonstrate
a + bmovinga; then rewrite with format!.
Next: ownership → (the big one)
Related Topics
Frequently Asked Questions about Strings
What is Strings in Rust?
Strings is a fundamental concept in Rust. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Strings?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Strings.
Why is Strings important in Rust?
Strings is essential for Rust development. Understanding this concept will help you write better code and solve real-world problems more effectively.