diff --git a/solutions/collections/String.md b/solutions/collections/String.md new file mode 100644 index 0000000..d6fcdd7 --- /dev/null +++ b/solutions/collections/String.md @@ -0,0 +1,114 @@ +1. +```rust +fn main() { + let mut s: String = String::from("hello, "); + s.push_str("world"); + s.push('!'); + + move_ownership(s.clone()); + + assert_eq!(s, "hello, world!"); + + println!("Success!") +} + +fn move_ownership(s: String) { + println!("ownership of \"{}\" is moved here!", s) +} +``` + +```rust +fn main() { + let mut s: String = String::from("hello, "); + s.push_str("world"); + s.push('!'); + + borrow_string(&s); + + assert_eq!(s, "hello, world!"); + + println!("Success!") +} + +fn borrow_string(s: &str) { + println!("ownership of \"{}\" is moved here!", s) +} +``` + +2. +```rust +// FILL in the blanks +fn main() { + // get a slice of String with reference: String -> &str + let mut s = String::from("hello, world"); + + let slice1: &str = &s; // in two ways + assert_eq!(slice1, "hello, world"); + + let slice2 = &s[0..5]; + assert_eq!(slice2, "hello"); + + //Note! The type here cant be `&mut str` due to `push` is ONLY defined on String type and its mut reference: `&mut String` ! + // So you can't use `s.as_mut_str()` + let slice3: &mut String = &mut s; + slice3.push('!'); + assert_eq!(slice3, "hello, world!"); + + println!("Success!") +} +``` + +```rust +fn main() { + let mut s = String::from("hello, world"); + + let slice1: &str = s.as_str(); + assert_eq!(slice1, "hello, world"); + + let slice2 = &s[0..5]; + assert_eq!(slice2, "hello"); + + //Note! The type here cant be `&mut str` due to `push` is ONLY defined on String type and its mut reference: `&mut String` ! + // So you can't use `s.as_mut_str()` + let slice3: &mut String = &mut s; + slice3.push('!'); + assert_eq!(slice3, "hello, world!"); + + println!("Success!") +} +``` + +2. +```rust +fn main() { + let s = String::from("hello, 世界"); + let slice1 = &s[0..1]; //modify this line to fix the error, tips: `h` only takes 1 byte in UTF8 format + assert_eq!(slice1, "h"); + + let slice2 = &s[7..10];//modify this line to fix the error, tips: `中` takes 3 bytes in UTF8 format + assert_eq!(slice2, "世"); + + println!("Success!") +} +``` + +3. +```rust +// FILL in the blanks +fn main() { + let mut s = String::new(); + s.push_str("hello"); + + // some bytes, in a vector + let v = vec![104, 101, 108, 108, 111]; + + // Turn a bytes vector into a String + // We know these bytes are valid, so we'll use `unwrap()`. + let s1 = String::from_utf8(v).unwrap(); + + + assert_eq!(s, s1); + + println!("Success!") +} +``` \ No newline at end of file diff --git a/src/SUMMARY.md b/src/SUMMARY.md index ea9e0b6..c53ec43 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -28,10 +28,10 @@ - [Traits](generics-traits/traits.md) - [Trait Object](generics-traits/trait-object.md) - [Advanced Traits](generics-traits/advanced-traits.md) -- [Collection Types todo](collections/intro.md) +- [Collection Types](collections/intro.md) - [String](collections/string.md) - - [Vector](collections/vector.md) - - [HashMap](collections/hashmap.md) + - [Vector todo](collections/vector.md) + - [HashMap todo](collections/hashmap.md) - [Type Conversion todo](type-conversion.md) - [Result and panic todo](result-panic/intro.md) - [panic!](result-panic/panic.md) diff --git a/src/collections/intro.md b/src/collections/intro.md index 1bdd607..db8e456 100644 --- a/src/collections/intro.md +++ b/src/collections/intro.md @@ -1 +1,6 @@ # Collection Types +Learning resources: +- English: [Rust Book Chapter 8](https://doc.rust-lang.org/book/ch08-00-common-collections.html) +- 简体中文: [Rust语言圣经 - 集合类型](https://course.rs/basic/collections/intro.html) + + diff --git a/src/collections/string.md b/src/collections/string.md index 2c0923c..fe96e82 100644 --- a/src/collections/string.md +++ b/src/collections/string.md @@ -1 +1,111 @@ # String +`std::string::String` is a UTF-8 encoded, growable string. It is the most common string type we used in daily dev, it also has ownership over the string contents. + +### Basic operations +1. 🌟🌟 +```rust,editable + +// FILL in the blanks and FIX errors +// 1. Don't use `to_string()` +// 2. Dont't add/remove any code line +fn main() { + let mut s: String = "hello, "; + s.push_str("world".to_string()); + s.push(__); + + move_ownership(s); + + assert_eq!(s, "hello, world!"); + + println!("Success!") +} + +fn move_ownership(s: String) { + println!("ownership of \"{}\" is moved here!", s) +} +``` + +### String and &str +A `String` is stored as a vector of bytes (`Vec`), but guaranteed to always be a valid UTF-8 sequence. `String` is heap allocated, growable and not null terminated. + +`&str` is a slice (`&[u8]`) that always points to a valid UTF-8 sequence, and can be used to view into a String, just like `&[T]` is a view into `Vec`. + +2. 🌟🌟 +```rust,editable +// FILL in the blanks +fn main() { + // get a slice of String with reference: String -> &str + let mut s = String::from("hello, world"); + + let slice1: &str = __; // in two ways + assert_eq!(slice1, "hello, world"); + + let slice2 = __; + assert_eq!(slice2, "hello"); + + let slice3: __ = __; + slice3.push('!'); + assert_eq!(slice3, "hello, world!"); + + println!("Success!") +} +``` + +### UTF-8 & Indexing +Strings are always valid UTF-8. This has a few implications: + +- the first of which is that if you need a non-UTF-8 string, consider [OsString](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html). It is similar, but without the UTF-8 constraint. +- The second implication is that you cannot index into a String + +Indexing is intended to be a constant-time operation, but UTF-8 encoding does not allow us to do this. Furthermore, it’s not clear what sort of thing the index should return: a byte, a codepoint, or a grapheme cluster. The bytes and chars methods return iterators over the first two, respectively. + +2. 🌟🌟🌟 You can't use index to access a char in a string, but you can use slice `&s1[start..end]`. + +```rust,editable + +// FIX errors +fn main() { + let s = String::from("hello, 世界"); + let slice1 = s[0]; //tips: `h` only takes 1 byte in UTF8 format + assert_eq!(slice1, "h"); + + let slice2 = &s[3..5];// tips: `中` takes 3 bytes in UTF8 format + assert_eq!(slice2, "世"); + + println!("Success!") +} +``` + + +3. 🌟🌟🌟 +> Tips: maybe you need `from_utf8` method + +```rust,editable + +// FILL in the blanks +fn main() { + let mut s = String::new(); + __; + + // some bytes, in a vector + let v = vec![104, 101, 108, 108, 111]; + + // Turn a bytes vector into a String + // We know these bytes are valid, so we'll use `unwrap()`. + let s1 = __; + + + assert_eq!(s, s1); + + println!("Success!") +} +``` + +### Representation + + + + + +### Common methods + diff --git a/zh-CN/src/generics-traits/advanced-traits.md b/zh-CN/src/generics-traits/advance-traits.md similarity index 100% rename from zh-CN/src/generics-traits/advanced-traits.md rename to zh-CN/src/generics-traits/advance-traits.md