Index
- Guessing Game
- Common Programming Concepts
- Understanding Ownership
- Using Structs
- Enums and Pattern Matching
- Managing Growing Projects with Packages, Crates, and Modules
- Defining Modules to Control Scope and Privacy
- Paths for Referring to an Item in the Module Tree
- Bringing Paths into Scope with the use Keyword
- Separating Modules into Different Files
- Common Collections
- Error Handling
- Generic Types, Traits, and Lifetimes
- Writing Automated Tests
- Object Oriented Programming
- Adding dependancies
- Option Take
- RefCell
- mem
- Data Structure
- Recipe
- Semi colon
- Calling rust from python
- Default
- Crytocurrency With rust
- Function chaining
- Question Mark Operator
- Tests with println
- lib and bin
- Append vector to hash map
- Random Number
- uuid4
- uwrap and option
- Blockchain with Rust
- Near Protocol
- Actix-web
Storing UTF-8 Encoded Text with Strings
Storing UTF-8 Encoded Text with StringsWhat Is a String?
We’ll first define what we mean by the term string. Rust has only one string type in the core language, which is the string slice
str
that is usually seen in its borrowed form &str
.Creating a New String
fn main() {
let mut s = String::new();
}
let mut s = String::new();
}
Often, we’ll have some initial data that we want to start the string with. For that, we use the
to_string
method, which is available on any type that implements the Display
trait, as string literals do let data = "initial contents";
let s = data.to_string();
// the method also works on a literal directly:
let s = "initial contents".to_string();
let s = data.to_string();
// the method also works on a literal directly:
let s = "initial contents".to_string();
str, only used as &str, is a string slice, a reference to a UTF-8 byte array.
String is what used to be ~str, a growable, owned UTF-8 byte array.
// owned String, heap allocated
let x = String::from("Hi");
// reference to string literal hardcoded in binary, 'static &str
let x = "Hi";
let x = String::from("Hi");
// reference to string literal hardcoded in binary, 'static &str
let x = "Hi";
String is the dynamic heap string type, like Vec: use it when you need to own or modify your string data.
str is an immutable sequence of UTF-8 bytes of dynamic length somewhere in memory. Since the size is unknown, one can only handle it behind a pointer. This means that str most commonly appears as &str: a reference to some UTF-8 data, normally called a "string slice" or just a "slice". A slice is just a view onto some data, and that data can be anywhere.
Remember that strings are UTF-8 encoded, so we can include any properly encoded data in them
fn main() {
let hello = String::from("السلام عليكم");
let hello = String::from("Dobrý den");
let hello = String::from("Hello");
let hello = String::from("שָׁלוֹם");
let hello = String::from("नमस्ते");
let hello = String::from("こんにちは");
let hello = String::from("안녕하세요");
let hello = String::from("你好");
let hello = String::from("Olá");
let hello = String::from("Здравствуйте");
let hello = String::from("Hola");
}
let hello = String::from("السلام عليكم");
let hello = String::from("Dobrý den");
let hello = String::from("Hello");
let hello = String::from("שָׁלוֹם");
let hello = String::from("नमस्ते");
let hello = String::from("こんにちは");
let hello = String::from("안녕하세요");
let hello = String::from("你好");
let hello = String::from("Olá");
let hello = String::from("Здравствуйте");
let hello = String::from("Hola");
}
All of these are valid
String
values.Updating a String
A
String
can grow in size and its contents can change, just like the contents of a Vec<T>
, if you push more data into it. In addition, you can conveniently use the +
operator or the format!
macro to concatenate String
values.Appending to a String with push_str and push
We can grow a
String
by using the push_str
method to append a string slice, let mut s = String::from("foo");
s.push_str("bar");
s.push_str("bar");
The
push_str
method takes a string slice because we don’t necessarily want to take ownership of the parameter.fn main() {
let mut s1 = String::from("foo");
let s2 = "bar";
s1.push_str(s2);
println!("s2 is {}", s2);
}
let mut s1 = String::from("foo");
let s2 = "bar";
s1.push_str(s2);
println!("s2 is {}", s2);
}
If the
push_str
method took ownership of s2
, we wouldn’t be able to print its value on the last line. However, this code works as we’d expect!The
push
method takes a single character as a parameter and adds it to the String
.fn main() {
let mut s = String::from("lo");
s.push('l');
}
let mut s = String::from("lo");
s.push('l');
}
Concatenation with the + Operator or the format! Macro
fn main() {
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used
}
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used
}
Read the details about deref coercion
If we need to concatenate multiple strings, the behavior of the
+
operator gets unwieldy: let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3;
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = s1 + "-" + &s2 + "-" + &s3;
For more complicated string combining, we can use the format! macro
fn main() {
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);
}
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);
}
This code also sets
s
to tic-tac-toe
. The format!
macro works in the same way as println!, but instead of printing the output to the screen, it returns a String
with the contents. The version of the code using format!
is much easier to read and doesn’t take ownership of any of its parameters.fn main() {
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);
println!("{}",s);
println!("{}", s1); // It prints, s1 is not moved
}
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);
println!("{}",s);
println!("{}", s1); // It prints, s1 is not moved
}
Indexing into Strings
Error code:
let s1 = String::from("hello");
let h = s1[0];
let h = s1[0];
Rust strings don’t support indexing. But why not? To answer that question, we need to discuss how Rust stores strings in memory.
For details link
Methods for Iterating Over Strings
for c in "नमस्ते".chars() {
println!("{}", c);
}
println!("{}", c);
}
This code will print the following:
न
म
स
्
त
े
म
स
्
त
े
The
bytes
method returns each raw byte, which might be appropriate for your domain:for b in "नमस्ते".bytes() {
println!("{}", b);
}
println!("{}", b);
}
This code will print the 18 bytes that make up this
String
:224
164
// --snip--
165
135
164
// --snip--
165
135