Home Rust Tutorial: Strings in Rust Programming Language

Tutorial: Strings in Rust Programming Language

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.

You may also like