Rust String Methods

Text appears in almost every program: names, messages, file contents, web addresses. Rust gives the String and &str types a rich set of methods for inspecting and reshaping text. The methods work like a sewing kit for words: measure, cut, join, patch, and press.

Measuring Text

The len method counts bytes, not visible characters. English letters use one byte each. Many other scripts and emoji use several bytes per character.

let word = String::from("Rust");
println!("{}", word.len());        // 4
println!("{}", word.is_empty());   // false

let hindi = "नमस्ते";
println!("{}", hindi.len());               // 18 bytes
println!("{}", hindi.chars().count());     // 6 characters

Use chars().count() when you need the number of visible characters.

Building and Growing Strings

let mut text = String::new();
text.push('H');           // add one character
text.push_str("ello");    // add a string slice
text.insert(0, '>');      // insert at a position
println!("{text}");       // >Hello

Joining with format!

The format! macro builds a new string from pieces, like println! without the printing.

let first = "Ada";
let last = "Lovelace";
let full = format!("{first} {last}");
println!("{full}");

Joining with the Plus Operator

The plus sign consumes the left string and borrows the right one.

let a = String::from("Good ");
let b = String::from("morning");
let c = a + &b;      // a is moved and no longer usable
println!("{c}");

Searching Inside Text

MethodResult
contains("ust")true when the piece appears
starts_with("Ru")true when the text begins with the piece
ends_with("st")true when the text ends with the piece
find("s")Some(position) or None
let line = "Rust is fast";
println!("{}", line.contains("fast"));   // true
println!("{:?}", line.find("is"));       // Some(5)

Changing Text

Transformation methods return new strings and leave the original untouched.

let title = "  Learn Rust  ";
println!("[{}]", title.trim());              // [Learn Rust]
println!("{}", title.to_uppercase());        //   LEARN RUST
println!("{}", title.to_lowercase());        //   learn rust
println!("{}", title.replace("Rust", "Go")); //   Learn Go

Trimming Variants

The trim_start and trim_end methods clean only one side. The trim_matches method removes chosen characters.

println!("{}", "***hi***".trim_matches('*'));   // hi

Splitting Text

Splitting breaks one string into smaller pieces, which suits CSV lines and sentences.

let data = "red,green,blue";
for color in data.split(',') {
    println!("{color}");
}

let words: Vec<&str> = "one two  three".split_whitespace().collect();
println!("{:?}", words);   // ["one", "two", "three"]
 "red,green,blue"
     |    |    |
     v    v    v
   "red" "green" "blue"

Splitting at a Fixed Spot

let (left, right) = "key=value".split_once('=').unwrap();
println!("{left} {right}");

Working with Characters

The chars method yields each character. The char_indices method adds byte positions.

for c in "abc".chars() {
    println!("{c}");
}

let reversed: String = "stressed".chars().rev().collect();
println!("{reversed}");   // desserts

Slicing Safely

A slice such as &text[0..4] uses byte positions. Cutting through the middle of a multi-byte character causes a panic. The get method returns an Option and avoids the crash.

let text = "Rustacean";
println!("{:?}", text.get(0..4));    // Some("Rust")
println!("{:?}", text.get(0..100));  // None

Converting Between Types

let s: String = "hello".to_string();   // &str to String
let r: &str = &s;                      // String to &str
let n: i32 = "42".parse().unwrap();    // text to number
let t = 42.to_string();                // number to text

Comparing Strings

The double equals sign compares content. Case matters, so convert both sides when you need a case-insensitive check.

println!("{}", "Rust" == "rust");                         // false
println!("{}", "Rust".to_lowercase() == "rust");          // true
println!("{}", "Rust".eq_ignore_ascii_case("rUST"));      // true

Common Mistakes

Indexing a string with a number, as in text[0], fails to compile. Rust refuses because a character may span several bytes. Use chars().nth(0) for a character or a slice for bytes.

Using the plus operator twice with the same left string causes a move error. The first plus consumes the left operand. Prefer format! when you join several pieces.

Assuming that len() reports the number of letters leads to wrong counts for non-English text. Count characters with chars().count().

Real-World Uses

  • Cleaning form input before saving it
  • Splitting comma-separated rows from a data file
  • Building web addresses and file names
  • Checking whether a message contains a banned word
  • Creating readable report lines with format!

Practice Ideas

  • Write a function that checks whether a word reads the same backward and forward.
  • Count the vowels in a sentence with chars() and a match.
  • Turn the text "first name,last name,age" into three separate variables.
  • Capitalize the first letter of every word in a title.

Method Chaining

String methods combine into short pipelines. The expression input.trim().to_lowercase().replace(" ", "-") cleans, lowers, and rewrites text in one line. Each method returns a new value for the next method to use, so the original text stays untouched until you decide to replace it.

Key Points

  • len counts bytes, and chars().count() counts characters.
  • Use push_str, format!, or + to build text.
  • split, trim, and replace reshape text without changing the original.
  • Slice with get to avoid panics on multi-byte text.