Rust Strings

Rust Strings

In the Rust programming language, a string is a sequence of Unicode characters. Strings are a non-primitive type in Rust that is found within the std library.

Strings can be created using either double quotes (") or backticks (`), with the latter allowing for interpolation of variables and expressions within the string. Rust also provides several methods for working with strings, such as concatenation, searching, slicing, and case conversion.

There are two kinds of strings in Rust: string literals and string objects. A string literal (abbreviated &str) is considered to be a string slice, and is stored on the stack. A string object, in contrast, is a surprisingly complex type of data structure, and is considered to be a collection (like a vector). Luckily we don’t need to know all the details of how strings work under the hood in order to start using them effectively.

In this article, we will cover the basics of strings including: an overview of strings in Rust, how to create a string, how to loop over a string, getting the length of a string, searching through a string, and a discussion on arrays vs. strings.

Strings in Rust are immutable by default, meaning they cannot be changed once they are created. However, they can be converted to a mutable version using the String::make_mut method.

Overall, strings in Rust offer a high level of flexibility and performance for working with text data in your programs.

Unlike other languages, strings in Rust are not null-terminated, which allows for more efficient memory usage and handling of strings with embedded null characters.

Creating Strings in Rust

To create a string in Rust, you can use the String type and the to_string() method:

let s = "Hello, world!".to_string();

Alternatively, you can use double quotes to create a string literal:

let s = "Hello, world!";

Both of these methods create an immutable string, meaning it cannot be changed once it is created. To create a mutable string, we need to use the mut keyword in the declaration, along with the .to_string() method:

let mut s = "Hello, world!".to_string();

Alternatively, we can use the String::new() method:

let mut s = String::new();

You can then use the push_str() method to add characters to the string:

s.push_str("Hello, world!");

Overall, there are many different ways to create strings in Rust, and the choice of method will depend on your specific needs and requirements.

Pushing Values Onto a String

We can push values onto an existing string by using the push_str() method:

fn main() {
    let s_lit = "Hello"; // String literal
    let mut s_obj = String::from(s_lit); //String object
    s_obj.push_str(", World!"); // Pushing a value
    println!("{}", s_obj); // Printing the string
}

Standard Output:

Hello, World!

In this example, we created a string literal called s_lit and then created the string object s_obj using the s_lit string literal. String literals can’t be mutated, but string objects can. We then used the push.str() method on s_obj in order to push the string “, World!”. Finally, we printed s_obj to the console.

Looping Through a String in Rust

We can use for to loop through a string in Rust. For example:

let s = "hello";

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

This will print each character in the string s on a separate line.

Note that this will loop through the Unicode scalar values of the string, which means that it will correctly handle characters that are represented by more than one byte (such as emojis). If you want to loop through the bytes of the string instead, you can use the .bytes() method instead of the .chars() method:

let s = "hello";

for b in s.bytes() {
    println!("{}", b);
}

This will print the byte values of each character in the string.

Alternatively to the for loop method, we can use a while loop and the next() method to manually advance to the next character:

let mut s = "Hello, world!";
let mut chars = s.chars();

while let Some(c) = chars.next() {
    // do something with each character in the string
}

Getting String Length in Rust

We can use the len() method to get the length of a string in Rust. This returns the number of characters in the string including whitespace or special characters:

let s = "Hello, world!";
let length = s.len();

println!("The string has {} characters", length);

Alternatively, we can use the chars() method on the string to get an iterator of its characters. Then we can use the count() method on the iterator to count the number of characters:

let s = "Hello, world!";

let length = s.chars().count();

println!("The string has {} characters", length);

Searching a String in Rust

Using find()

We can use the find() method to search a string.

This method takes a string or character as an argument and returns the position of the first occurrence of that string or character in the original string.

let s = "Hello, world!";

let position = s.find("world");

println!("'world' was found at position {}", position.unwrap());

If the search string or character is not found in the original string, the find() method will return None.

Using contains()

We can use the contains() method on the string to check if a given string or character is present in the original string without getting the position of the match.

let s = "Hello, world!";

if s.contains("world") {
    println!("The string contains 'world'");
} else {
    println!("The string does not contain 'world'");
}

Using Regex

We can use the regex crate to search for a string using regular expressions. Here’s an example:

extern crate regex;

use regex::Regex;

fn main() {
    let re = Regex::new(r"hello").unwrap();
    let text = "hello world";

    if re.is_match(text) {
        println!("Found a match!");
    }
}

In this code, we created a new regular expression by calling Regex::new(r"hello").

The r before the string indicates that it’s a raw string, which means that backslashes are treated as regular characters (instead of escape characters).

Next, we created a string that we want to search, called text. Then, we call is_match on the Regex object and pass in the text string. This will return true if the regular expression matches the string, and false otherwise.

If a match is found, we print a message to the console using the println! macro.

Are Strings Arrays in Rust?

While strings are sequences of characters, they are not implemented as arrays in Rust. Instead, strings are represented by the String type, which is a heap-allocated, growable, and mutable data structure.

In contrast, arrays are fixed-size collections of values of the same type. Arrays are stored in contiguous memory and are represented by the [T; N] syntax, where T is the type of the elements and N is the length of the array.

While strings and arrays are both used to store collections of values, they are different data structures with different properties and behaviors. As such, they cannot be directly interchanged in Rust code.