Skip to main content
Brave Programmer Logo

BraveProgrammer

BraveProgrammer

HomeProjectsBlogsCoursesLessonsAbout

Site footer

BraveProgrammer

Free coding courses, practical tutorials, and real projects from BraveProgrammer. Learn web development with React, Next.js, and TypeScript.

Navigation

  • Home
  • Projects
  • Blogs
  • Courses

Resources

  • About
  • Lessons

© 2026 BraveProgrammer. All rights reserved.

  1. Courses
  2. /
  3. Rust Fundamentals

Lesson 12 of 50 · rust

Strings

Duration: 13 minutes

Strings\n\nRust has two primary string types, each serving different purposes.\n\n## String vs &str\n\n### String\n- Owned, growable, heap-allocated text\n- Mutable by default (if declared mut)\n- Created with String::from() or .to_string()\n\n### &str\n- Borrowed string slice\n- Fixed size, immutable\n- String literals are &str\n\nrust\nlet s1: String = String::from(\"hello\"); // Owned\nlet s2: &str = \"world\"; // Borrowed (literal)\nlet s3: &str = &s1[..]; // Slice of String\n\n\n## Working with Strings\n\nrust\nfn main() {\n let mut s = String::from(\"Hello\");\n \n // Append string\n s.push_str(\", \");\n \n // Push single character\n s.push('W');\n \n // Concatenation with +\n let s2 = s + \"orld\"; // \"Hello, World\"\n \n // Format macro\n let s3 = format!(\"{}, {}\", s2, \"Rust\");\n}\n\n\n## String Operations\n\n### Length and Capacity\n\nrust\nlet s = String::from(\"hello\");\nprintln!(\"Length: {}\", s.len()); // 5 bytes\nprintln!(\"Capacity: {}\", s.capacity()); // Allocated space\n\n\n### Iteration\n\nrust\nlet s = \"hello\";\n\n// Bytes\nfor b in s.as_bytes() {\n println!(\"Byte: {}\", b);\n}\n\n// Characters (handles Unicode)\nfor c in s.chars() {\n println!(\"Char: {}\", c);\n}\n\n\n### Search and Replace\n\nrust\nlet s = \"hello world\";\nprintln!(\"Contains 'world': {}\", s.contains(\"world\")); // true\nprintln!(\"Starts with 'hello': {}\", s.starts_with(\"hello\")); //true\n\nlet replaced = s.replace(\"world\", \"Rust\");\nprintln!(\"Replaced: {}\", replaced); // \"hello Rust\"\n\n\n## Important: String Indexing\n\nYou cannot index strings with integers directly:\n\nrust\nlet s = String::from(\"hello\");\n// let c = s[0]; // ERROR!\n\n\nWhy? Strings are UTF-8 encoded, and characters can be multiple bytes. Use slicing or iteration instead:\n\nrust\nlet first_char = &s[0..1]; // Valid\n\n\n## Unicode Considerations\n\nrust\nlet s = \"hello\"; // Purely ASCII\nprintln!(\"Len: {}\", s.len()); // 5\n\nlet emoji = \"🦀\"; // 4 bytes\nprintln!(\"Len: {}\", emoji.len()); // 4 (bytes), not 1\nprintln!(\"Chars: {}\", emoji.chars().count()); // 1 (character)\n\n\n## String Conversion\n\nrust\nlet num = 42;\nlet s = num.to_string(); // \"42\"\n\nlet s2 = String::from(\"123\");\nlet num2: i32 = s2.parse().unwrap(); // 123\n\n\n## Best Practices\n\n1. Use &str for function parameters when possible\n2. Use String when you need to own the data\n3. Remember strings are UTF-8\n4. Use slicing, not indexing\n5. Use .to_string() for easy conversions

Previous: SlicesNext: Structs