39
Strings are a core part of programming, and Rust provides powerful, safe, and efficient ways to handle them.
Rust has two main types of strings: String (growable, heap-allocated string) and &str (string slice).
This tutorial will help you understand and work effectively with strings in Rust.
What You'll Learn
1. String Types in Rust
String
- A heap-allocated, growable string.
- Best for dynamically-sized string content.
&str (String Slice)
- A view into a string, often used for string literals.
- Immutable and usually more lightweight.
Example: Difference Between String and &str
fn main() { let slice: &str = "Hello, world!"; // String slice (immutable) let string: String = String::from("Hello, Rust!"); // Growable String println!("slice: {}", slice); println!("string: {}", string); }
2. Creating Strings
From String Literals
fn main() { let s1 = String::from("Hello, Rust!"); // Using `from` let s2 = "Hello, world!".to_string(); // Using `to_string` println!("{}", s1); println!("{}", s2); }
Empty String
fn main() { let empty = String::new(); // Create an empty String println!("Length: {}", empty.len()); }
3. String Slices (&str)
Immutable String Literals
fn main() { let slice: &str = "This is a string slice."; println!("{}", slice); }
Slicing a String
fn main() { let string = String::from("Hello, Rust!"); let slice = &string[0..5]; // Get a slice of the first 5 characters println!("Slice: {}", slice); }
4. Modifying Strings
Appending to Strings
fn main() { let mut s = String::from("Hello"); s.push('!'); // Append a single character s.push_str(" Rust!"); // Append a string slice println!("{}", s); }
Removing Characters
fn main() { let mut s = String::from("Hello, Rust!"); s.pop(); // Removes and returns the last character println!("{}", s); s.truncate(5); // Truncate to the first 5 characters println!("{}", s); }
5. Concatenation and Formatting
Concatenation with +
fn main() { let s1 = String::from("Hello, "); let s2 = String::from("Rust!"); let s3 = s1 + &s2; // s1 is moved, and s2 is borrowed println!("{}", s3); }
Concatenation with format!
fn main() { let s1 = String::from("Hello"); let s2 = String::from("Rust"); let s3 = format!("{}, {}!", s1, s2); // s1 and s2 are not moved println!("{}", s3); }
6. Iterating Over Strings
Iterate Over Characters
fn main() { let s = String::from("Rust"); for c in s.chars() { println!("{}", c); } }
Iterate Over Bytes
fn main() { let s = String::from("Rust"); for b in s.bytes() { println!("{}", b); } }
7. String Methods
Common Methods
fn main() { let s = String::from("Hello, Rust!"); println!("Length: {}", s.len()); // Length of the string println!("Is empty: {}", s.is_empty()); // Check if empty println!("Contains 'Rust': {}", s.contains("Rust")); // Substring check println!("Replace 'Rust' with 'World': {}", s.replace("Rust", "World")); }
Splitting Strings
fn main() { let s = String::from("Hello, Rust World!"); for part in s.split(' ') { println!("{}", part); } }
8. Conversions Between String and &str
String to &str
fn main() { let s = String::from("Hello"); let slice: &str = &s; // Borrow as a string slice println!("{}", slice); }
&str to String
fn main() { let slice: &str = "Hello, Rust!"; let string = slice.to_string(); // Convert to String println!("{}", string); }
9. Practical Examples
9.1 Reverse a String
fn main() { let s = String::from("Rust"); let reversed: String = s.chars().rev().collect(); println!("Reversed: {}", reversed); }
9.2 Count Vowels in a String
fn main() { let s = String::from("Hello, Rust!"); let vowels = "aeiouAEIOU"; let count = s.chars().filter(|c| vowels.contains(*c)).count(); println!("Number of vowels: {}", count); }
9.3 Check if a String is a Palindrome
fn main() { let s = String::from("madam"); let is_palindrome = s.chars().eq(s.chars().rev()); println!("Is '{}' a palindrome? {}", s, is_palindrome); }
9.4 Split and Capitalize Words
fn main() { let sentence = String::from("rust programming language"); let capitalized: Vec<String> = sentence .split_whitespace() .map(|word| { let mut c = word.chars(); c.next() .unwrap() .to_uppercase() .chain(c) .collect::<String>() }) .collect(); println!("{}", capitalized.join(" ")); }
10. Summary
Key Features
- Rust has two primary string types:
- String: Growable, heap-allocated, and mutable.
- &str: Immutable and lightweight.
- Strings are UTF-8 encoded, meaning they can store characters from almost all languages.
- Rust enforces safety, preventing common pitfalls like out-of-bounds access.
Common Use Cases
- Use String for dynamic string operations.
- Use &str for static, immutable string slices.
- Use methods like split, chars, replace, and len for efficient string manipulation.
Mastering strings in Rust is key to building efficient text-processing applications.