Str example. To begin, we use the str primitive type in this example. String literals are of type str—they cannot grow dynamically.
Part 1 We create a primitive string array of length 2. The elements "bird" and "frog" are added to the array at creation time.
Part 2 We use a for-loop over the animals array. We access each element and print it with println.
Part 3 We mutate the array (which was specified with the mut keyword) and then print the elements again.
fn main() {
// Part 1: create string array.
let mut animals: [&str; 2] = ["bird", "frog"];
// Part 2: loop over elements in string array.
for animal in &animals {
println!("For: {}", animal);
}
// Part 3: change element in string array.
animals[0] = "cat";
println!("Element 0: {}", animals[0]);
println!("Element 1: {}", animals[1]);
}For: bird
For: frog
Element 0: cat
Element 1: frog
Growable String array. To create an array of growable strings, we can use the String type, and then call to_string() on string literals. These Strings can be appended to in-place.
Part 1 We create the String array with an initializer expression. We call to_string() on each element in the initialization.
Part 2 We use a for-loop over the colors array, and print each element with a println function call.
fn main() {
// Part 1: create array of type String.// ... Use to_string for elements.
let colors: [String; 2] = ["red".to_string(), "blue".to_string()];
// Part 2: print elements.
for value in &colors {
println!("For: {}", value);
}
}For: red
For: blue
Iter loop. For string arrays, we can use iter() to loop over the array elements. Here we have an array of ID string literals, and we use iter to iterate them.
Tip In this program we could omit the iter() call as well as the type of the "ids" array—the program would still be the same.
fn main() {
let ids: [&str; 3] = ["x100", "y200", "z300"];
// Loop over the array by calling iter() which returns a slice.
for value in ids.iter() {
println!("ITER: {}", value);
}
}ITER: x100
ITER: y200
ITER: z300
String Vec. Sometimes we want to create a collection of strings that we can add to—a string Vec is ideal here. We create the vector with vec, and then can push items to the collection.
Info We use the "vec!" macro to initialize the Vec with 2 str primitives. Then we call push() to add 2 more strings.
Tip We must specify the mut keyword for a mutable vector: this allows us to change it by calling push().
fn main() {
let mut places = vec!["Paris", "New York"];
places.push("Madrid");
places.push("Toronto");
for place in &places {
println!("PLACE: {}", place)
}
}PLACE: Paris
PLACE: New York
PLACE: Madrid
PLACE: Toronto
Array argument. We often need to pass arrays as arguments to functions. To receive an array argument, we specify its type in the formal parameter list.
Here The test() fn receives a 2-element str primitive array. It prints the length when in the function body.
Vector argument. In the modify_vec function, we pass a mutable reference to a string vector. So we can modify the vector in the called function (and the program compiles).
Note By passing a Vec as an argument, we can append many values to a vector (like bytes from a string) in a function.
fn modify_vec(values: &mut Vec<&str>) {
// Modify the string vector argument.
values.push("bird");
}
fn main() {
let mut animals = vec!["dog"];
// Pass a mut reference to allow vector to be modified in another function.
modify_vec(&mut animals);
println!("RESULT: {:#?}", animals);
}RESULT: [
"dog",
"bird",
]
Get element. How can we get an element from a String vector? We can use the get() function, which returns an Option. If the index is in-range, the element is returned.
Tip We can use the if-let syntax to get the inner value of the option as a local variable (here we call it "first").
fn main() {
// 1-element string vec.
let mut values = vec![String::from("cat")];
// Use get on an element in the string vector.
if let Some(first) = values.get(0) {
println!("FIRST: {first}");
}
// If the index is out of range, no panic occurs.
if let Some(test) = values.get(400) {
// Not reached.
}
}FIRST: cat
Convert array, vector. We can convert arrays and vectors to slices and use them in a unified way. Here the test() function receives a string slice.
Part 1 We create a string vector, and then call as_slice() to use the vector as a string slice argument.
Part 2 We create an array. Then we borrow the array and pass it to the test function as a slice.
Part 3 We create an array here too, but borrow it in the same statement as a slice. We pass the variable as a slice.
fn test(values: &[&str]) {
println!("SLICE LEN: {}", values.len())
}
fn main() {
// Part 1: use as_slice to convert Vector to slice.
let shapes = vec!["square", "circle"];
test(shapes.as_slice());
// Part 2: use array as slice argument.
let shapes2: [&str; 2] = ["square", "circle"];
test(&shapes2);
// Part 3: get slice from array, and pass as argument.
let shapes3: &[&str] = &["square", "circle"];
test(shapes3);
}SLICE LEN: 2
SLICE LEN: 2
SLICE LEN: 2
Split, Vec. We can place the results of the split() function into a String vector with collect(). Here we get a String vector from split and then pretty-print the results.
fn main() {
let test = "abc def";
// Call split, and use collect() to get a string Vec.
let values: Vec<&str> = test.split(' ').collect();
// Pretty-print the results.
println!("VALUES: {:?}", values)
}VALUES: ["abc", "def"]
With capacity. Suppose we know how many Strings we want in a vector. We can provide that number to with_capacity, and then push() the Strings.
Info Here we want to push 100 strings to the vector, so we use with_capacity with an argument of 100.
Tip With_capacity is a performance optimization as it reduces allocations and Vec copies if the capacity was too low.
Here In this program, we want a Vec of Strings, not str references, so we call to_string.
Important In Rust programs using String instead of str is easiest, and we can reduce copying with Arcs.
fn main() {
// Create a Vec of Strings, and use a capacity to avoid resizes.
let mut birds = Vec::with_capacity(100);
for _ in 0..100 {
// We call to_string() to have String and not str references.
birds.push("bird".to_string());
}
println!("Bird count: {}", birds.len());
}Bird count: 100
Enumerate. Sometimes we want to use a for-in loop over a String Vec or array in Rust. But we may also want the index for some reason.
So We can use enumerate() to get index and element pairs from each position in an array.
Tip This can simplify and improve certain loops in Rust programs. We must use iter() before calling enumerate().
fn main() {
let colors = vec!["blue", "green", "yellow"];
// Call enumerate to get index, value pairs in a for-loop.
for (i, color) in colors.iter().enumerate() {
println!("INDEX = {}, COLOR = {}", i, color);
}
}INDEX = 0, COLOR = blue
INDEX = 1, COLOR = green
INDEX = 2, COLOR = yellow
Repeated, empty. We can create a vector of a single string repeated many times—think of this as a default value string vector. The second "vec" macro argument is the repeat count.
Also The example shows how to clear a string vector, which leaves its length as 0, so the is_empty() function will return true.
fn main() {
// Create a string vector of 5 repeated strings.
let mut repeated_values = vec!["A123".to_string(); 5];
println!("{:?}", repeated_values);
// Clear the vector.
repeated_values.clear();
println!("{:?}", repeated_values);
// See if the vector is empty.
if repeated_values.is_empty() {
println!("IS EMPTY");
}
}["A123", "A123", "A123", "A123", "A123"]
[]
IS EMPTY
To create string arrays, we can use array syntax like any other array in Rust. But we must choose between string primitives (str) and Strings. Strings are more usable.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.