03-rust复合类型

1.字符串和切片

什么是字符串?

Rust 中的字符是 Unicode 类型,因此每个字符占据 4 个字节内存空间,但是在字符串中不一样,字符串是 UTF-8 编码,也就是字符串中的字符所占的字节数是变化的(1 - 4)

str 类型是硬编码进可执行文件,也无法被修改,但是 String 则是一个可增长、可改变且具有所有权的 UTF-8 编码字符串,当 Rust 用户提到字符串时,往往指的就是 String 类型和 &str 字符串切片类型,这两个类型都是 UTF-8 编码

1
2
3
4
5
6
let a = [1, 2, 3, 4, 5];

let slice = &a[1..3];

assert_eq!(slice, &[2, 3]);

String 与 &str 的转换

1
2
3
4
5
6
7
8
9
10
fn main() {
let s = String::from("hello,world!");
say_hello(&s);
say_hello(&s[..]);
say_hello(s.as_str());
}

fn say_hello(s: &str) {
println!("{}",s);
}

字符串索引

字符串切片

通过索引区间来访问字符串时,需要格外的小心,一不注意,就会导致你程序的崩溃!

操作字符串

追加 (Push)

插入 (Insert)

替换 (Replace)

删除 (Delete)

连接 (Concatenate)

字符串转义

1
2
3
4
5
6
7
8
9
10
11
12
13
fn main() {
println!("{}", "hello \\x52\\x75\\x73\\x74");
let raw_str = r"Escapes don't work here: \x3F \u{211D}";
println!("{}", raw_str);

// 如果字符串包含双引号,可以在开头和结尾加 #
let quotes = r#"And then I said: "There is no escape!""#;
println!("{}", quotes);

// 如果还是有歧义,可以继续增加,没有限制
let longer_delimiter = r###"A string with "# in it. And even "##!"###;
println!("{}", longer_delimiter);
}

操作 UTF-8 字符串

字符串与切片 - Rust语言圣经(Rust Course)

1
2
3
for c in "中国人".chars() {
println!("{}", c);
}

课后练习

Rust By Practice,支持代码在线编辑和运行,并提供详细的习题解答。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

// 填空并修复错误
fn main() {
let s = String::from("hello, 世界");
let slice1 = &s[0..1]; //提示: `h` 在 UTF-8 编码中只占用 1 个字节
assert_eq!(slice1, "h");

let slice2 = &s[7..10];// 提示: `世` 在 UTF-8 编码中占用 3 个字节
assert_eq!(slice2, "世");

// 迭代 s 中的所有字符
for (i, c) in s.chars().enumerate() {
if i == 7 {
assert_eq!(c, '世')
}
}

println!("Success!")
}



// 填空
fn main() {
let mut s = String::new();
s.push_str("hello");

let v = vec![104, 101, 108, 108, 111];

// 将字节数组转换成 String
let s1 = String::from_utf8(v).unwrap();


assert_eq!(s, s1);

println!("Success!")
}



// 填空
use std::mem;

fn main() {
let story = String::from("Rust By Practice");

// 阻止 String 的数据被自动 drop
let mut story = mem::ManuallyDrop::new(story);

let ptr = story.as_mut_ptr();
let len = story.len();
let capacity = story.capacity();

assert_eq!(16, len);

// 我们可以基于 ptr 指针、长度和容量来重新构建 String.
// 这种操作必须标记为 unsafe,因为我们需要自己来确保这里的操作是安全的
let s = unsafe { String::from_raw_parts(ptr, len, capacity) };

assert_eq!(*story, s);

println!("Success!")
}

2.元组

3. 元组

4. test

待续。。。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 yengii@qq.com