18.2 The String Type

String is a growable, heap-allocated UTF-8 text buffer, similar to a Vec<u8> but guaranteed to hold valid UTF-8.

18.2.1 Comparing &str and String

  • &str: Immutable borrowed view into text data.
  • String: Owned, mutable UTF-8 text buffer.

Use &str for borrowing, String for owning and modifying text.

18.2.2 Comparing String and Vec<u8>

String ensures UTF-8 validity, while Vec<u8> is arbitrary binary data. Conversions are straightforward, but String::from_utf8() fails on invalid data.

18.2.3 Creating Strings

  • From literals:

    #![allow(unused)]
    fn main() {
    let s = String::from("Hello");
    let s2 = "Hello".to_string();
    }
  • From other data:

    #![allow(unused)]
    fn main() {
    let number = 42;
    let s = number.to_string(); // "42"
    }
  • Empty String:

    #![allow(unused)]
    fn main() {
    let mut s = String::new();
    s.push_str("Hello");
    }
  • Concatenation:

    #![allow(unused)]
    fn main() {
    let s1 = String::from("Hello");
    let s2 = String::from("World");
    let combined = s1 + " " + &s2; // s1 is moved
    }
  • Using format!:

    #![allow(unused)]
    fn main() {
    let name = "Alice";
    let age = 30;
    let s = format!("{} is {} years old.", name, age);
    }

18.2.4 UTF-8 Implications

String cannot be directly indexed by integers because UTF-8 characters can have varying byte lengths. Use .chars() or .bytes() to iterate. Complex Unicode handling may require external crates.

18.2.5 Common String Methods

  • Appending:

    #![allow(unused)]
    fn main() {
    let mut s = String::from("Hello");
    s.push(' ');
    s.push_str("World!");
    }
  • Replacing:

    #![allow(unused)]
    fn main() {
    let s = "I like apples.".to_string();
    let replaced = s.replace("apples", "bananas");
    }
  • Splitting & Joining:

    #![allow(unused)]
    fn main() {
    let s = "apple,banana,orange".to_string();
    let parts: Vec<&str> = s.split(',').collect();
    let joined = parts.join(" & ");
    }
  • Iterating:

    #![allow(unused)]
    fn main() {
    for ch in "Hello".chars() {
        println!("{}", ch);
    }
    }

18.2.6 Handling Unicode

For grapheme clusters and complex Unicode features, use external crates like unicode-segmentation.

18.2.7 Summary

String provides flexible, owned UTF-8 text handling. While &str references text slices, String allows dynamic and safe text manipulation.