String Operations

Back

Loading concept...

Rust String Operations: Your Magic Toolbox for Words

The Big Picture: Strings Are Like LEGO Blocks

Imagine you have a box of LEGO blocks. Each block is a letter or symbol. When you snap them together, you build words and sentences. In Rust, we call this collection of blocks a String.

But here’s the cool part: Rust gives you special powers to:

  • Glue blocks together (concatenation)
  • Paint them nicely (format! macro)
  • Cut out pieces (slicing)
  • Look at each block one by one (iteration)
  • Handle blocks from ANY language (UTF-8 encoding)
  • Work with raw building material (byte strings)

Let’s explore each superpower!


1. String Concatenation: Gluing Words Together

What Is It?

Concatenation means joining strings together — like snapping LEGO blocks to make a longer train.

The Story

You have two toy trains: “Hello” and “World”. You want one BIG train: “HelloWorld”. That’s concatenation!

Method 1: Using the + Operator

let s1 = String::from("Hello");
let s2 = String::from(" World");
let result = s1 + &s2;
// result = "Hello World"
// Note: s1 is MOVED (gone!)

Important Rule: The first string (s1) gets consumed (used up). The second string needs a & (we’re just borrowing it).

Method 2: Using push_str()

let mut greeting = String::from("Hi");
greeting.push_str(" there!");
// greeting = "Hi there!"

Method 3: Using push() for Single Characters

let mut word = String::from("Hel");
word.push('l');
word.push('o');
// word = "Hello"

Quick Tip

Think of push as adding ONE block. Think of push_str as adding a WHOLE row of blocks.


2. The format! Macro: The Smart Painter

What Is It?

format! is like a magic stencil. You write a template with holes, and Rust fills in the blanks beautifully.

The Story

Imagine making birthday cards. You don’t write each card from scratch. You have a template:

“Happy Birthday, _____! You are _____ years old!”

You just fill in the blanks. That’s what format! does!

Basic Example

let name = "Luna";
let age = 8;
let card = format!(
    "Happy Birthday, {}! You're {} today!",
    name, age
);
// card = "Happy Birthday, Luna!
//         You're 8 today!"

Why Use format! Instead of +?

Method Ownership Readability
+ operator Takes first string Gets messy
format! Borrows ALL strings Clean & clear

Named Placeholders (Even Cooler!)

let msg = format!(
    "{animal} says {sound}!",
    animal = "Cat",
    sound = "Meow"
);
// msg = "Cat says Meow!"

Pro Tip: format! creates a NEW String. Your original strings stay safe!


3. String Slicing: Cutting Out Pieces

What Is It?

Slicing means taking a piece of a string — like cutting a slice of pizza from a whole pie.

The Story

You have a word: “RAINBOW”. You only want the “BOW” part. Slicing lets you cut it out!

How It Works

let word = String::from("RAINBOW");
let slice = &word[4..7];
// slice = "BOW"

Understanding the Numbers

R  A  I  N  B  O  W
0  1  2  3  4  5  6  7
         ^        ^
       start    end (not included)
  • [4..7] means: Start at position 4, stop BEFORE position 7
  • The result: B (pos 4), O (pos 5), W (pos 6)

Slice Shortcuts

let s = String::from("Hello");

let first_two = &s[..2];   // "He"
let last_three = &s[2..];  // "llo"
let all = &s[..];          // "Hello"

The Danger Zone

Slicing at wrong positions causes PANIC!

let emoji = String::from("Hi");
// let bad = &emoji[0..3]; // CRASH!
// You can't cut in the middle
// of a character!

4. String Iteration: Looking at Each Block

What Is It?

Iteration means going through each piece one by one — like a detective examining each clue.

The Story

You’re a detective with a secret message: “RUST”. You need to look at each letter to crack the code!

Method 1: Iterate Over Characters

let word = String::from("RUST");
for ch in word.chars() {
    println!("Letter: {}", ch);
}
// Output:
// Letter: R
// Letter: U
// Letter: S
// Letter: T

Method 2: Iterate Over Bytes

let word = String::from("Hi");
for byte in word.bytes() {
    println!("Byte: {}", byte);
}
// Output:
// Byte: 72  (H in ASCII)
// Byte: 105 (i in ASCII)

Method 3: Characters with Index

for (i, ch) in "Cat".chars().enumerate() {
    println!("Position {}: {}", i, ch);
}
// Position 0: C
// Position 1: a
// Position 2: t

When to Use What?

Method Use When
.chars() Working with letters/symbols
.bytes() Working with raw data
.enumerate() Need position + value

5. UTF-8 Encoding: The Universal Translator

What Is It?

UTF-8 is a magical translation system that lets Rust understand letters from EVERY language in the world!

The Story

Imagine a library with books in English, Japanese, Arabic, and Emoji language. UTF-8 is the librarian who can read them ALL!

Why It Matters

let hello_world = String::from("Hello");
let japanese = String::from("");
let emoji = String::from("");
// Rust handles ALL of these!

The Byte Reality

Different characters need different amounts of space:

let a = "a";        // 1 byte
let omega = "";    // 2 bytes
let chinese = "";  // 3 bytes
let emoji = "";   // 4 bytes

println!("{}", a.len());      // 1
println!("{}", omega.len());  // 2
println!("{}", chinese.len());// 3
println!("{}", emoji.len());  // 4

Counting Characters vs Bytes

let word = "";  // "water" in Japanese
println!("Bytes: {}", word.len());
// Bytes: 6
println!("Chars: {}", word.chars().count());
// Chars: 2

Why Slicing Can Be Tricky

String:    "a"  ""
Bytes:     [97] [240, 159, 152, 138]
Position:   0    1   2   3   4

You CAN slice at: 0, 1, 5
You CANNOT slice at: 2, 3, 4

6. Byte Strings and Byte Literals: The Raw Materials

What Is It?

Byte strings are raw building blocks — like looking at the actual LEGO plastic instead of the finished toys.

The Story

Sometimes you need to work with the raw ingredients, not the finished cake. Byte strings let you do that!

Byte Literals

let byte_string: &[u8] = b"Hello";
// This is NOT a String
// It's raw bytes: [72, 101, 108, 108, 111]

Comparing String vs Byte String

let text = "Hello";       // &str (text)
let bytes = b"Hello";     // &[u8] (raw bytes)

println!("{:?}", text);   // "Hello"
println!("{:?}", bytes);  // [72, 101, 108, 111]

Converting Between Them

// String to Bytes
let s = String::from("Rust");
let bytes = s.as_bytes();
// [82, 117, 115, 116]

// Bytes to String (when valid UTF-8)
let bytes = vec![82, 117, 115, 116];
let s = String::from_utf8(bytes).unwrap();
// "Rust"

Escape Sequences in Byte Strings

let escaped = b"Line1\nLine2";
// \n = newline character
// Result: two lines!

let tab = b"Col1\tCol2";
// \t = tab character

When to Use Byte Strings?

Use Case Type
Text for humans String or &str
File contents &[u8] or Vec<u8>
Network data &[u8] or Vec<u8>
Binary files &[u8] or Vec<u8>

The Complete Picture

graph TD A["Rust Strings"] --> B["Create &amp; Join"] A --> C["Look Inside"] A --> D["Raw Data"] B --> B1["+ operator"] B --> B2["push/push_str"] B --> B3["format! macro"] C --> C1["Slicing"] C --> C2[".chars iteration"] C --> C3[".bytes iteration"] D --> D1["UTF-8 encoding"] D --> D2["Byte strings"] D --> D3["Conversions"]

Quick Reference Card

Operation Code Result
Concatenate s1 + &s2 Joins strings
Format format!("{}", x) New string
Slice &s[1..3] Substring
Chars s.chars() Iterator
Bytes s.bytes() Byte iterator
Length (bytes) s.len() Number
Length (chars) s.chars().count() Number
To bytes s.as_bytes() &[u8]

You Did It!

You now have 6 superpowers for working with Rust strings:

  1. Concatenation — Glue words together
  2. format! — Smart templates
  3. Slicing — Cut out pieces
  4. Iteration — Examine each part
  5. UTF-8 — Handle any language
  6. Byte strings — Work with raw data

Remember: Strings in Rust are like LEGO blocks. You can build, cut, examine, and transform them in any way you want. Now go build something amazing!

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.