Rust入门-07-切片
切片(slice)
-
slice是一个没有所有权的数据类型
- slice 允许引用集合中一段连续的元素序列,而不用引用整个集合
//该函数接收一个字符串,返回在字符串中找到第一个单词 //如果在字符串中没有找到空格,就返回整个字符串 fn first_word(s: &String) -> usize { let bytes = s.as_bytes(); //as_bytes 将 String 转化为字节数组 for (i, &item) in bytes.iter().enumerate() { //使用iter方法在字节数组上创建一个迭代器 //iter会依次返回集合中的每一个元素 //enumerate 会包装 iter 的结果, //并将这些元素作为元组的一部分来返回 //enumerate 返回的元组中, //第一个元素是索引,第二个元素是集合中元素的引用 if item == b' ' { return i; } } s.len() }该代码有一个缺陷:函数返回的索引值
usize是独立的,只在&String的上下文中才有意义。那么当函数返回值以后,就无法保证其的有效性fn main() { let mut s = String::from("hello world"); let word = first_word(&s); // word 的值为 5 s.clear(); // 清空了字符串,使其变成一个空的字符串 // 但 word 在此处的值仍然是 5,即索引的值仍然是 5 // 此时 word 的值是无效的,不能在 s 中找到对应的值 // 即将 5 保存到word中时,s 的内容已经发生变化了 }所以在设计这类问题时,需要时刻关注 word 的有效性,以及 s 和其索引值 word 的同步性
这样会很繁琐
字符串切片(string slice)
-
字符串切片是
String中一部分值的引用- 可以写为 &str
let s = String::from("hello world"); let hello = &s[0..5]; //即s中索引值为0,1,2,3,4的元素,包括0,但不包括5 let world = &s[6..11]; -
形式:[开始索引..结束索引]
- 开始索引就是切片起始位置的索引值
- 结束索引是切片终止位置的下一个索引值
( world 是从 s 字符串索引值从 6 到 11
-
字符串切片的语法(语法糖
-
如果从索引 0 开始,可以省略两个点号之前的值
let slice = &s[0..2];let slice = &s[..2]; -
如果切片包含String的最后一个字符,可以省略两个点号之后的值
let slice = &s[3..len];let slice = &s[3..]; -
如果切片指向String整个字符串,可以同时省略两个点号前后的值
let slice = &s[0..len];let slice = &s[..];
-
-
注意:
- 字符串 slice range 的索引必须位于有效的 UTF-8 字符(?边界内
- 如果尝试从一个多字节字符的中间位置创建字符串 slice,则程序会报错而退出
-
使用字符串切片重新写开头的例子
fn first_word(s: &String) -> &str { //原本的例子为 usize let bytes = s.as_bytes(); //现在的&str引用作为返回值 //可以确保该引用持续有效 for (i, &item) in bytes.iter().enumerate() { if item == b' ' { return &s[0..i]; //原本的例子为return i } //现在如果集合的元素为空格,就将其切片返回 } &s[..] //原本的例子为 s.len //现在如果没有在集合中找到空格,就将其整个返回 }
字符串字面值就是切片
-
s的类型就是&str&str是不可变引用,所以字符串字面值也是不可变的
let s = "Hello, world!";
字符串切片作为参数
-
当用
&str为参数类型时,可以同时接收String和&str类型的参数fn first_word(s: &str) -> &str {- 使用字符串切片,可以直接调用该函数
- 使用String,可以创建一个完整的String切片来调用函数
-
eg
fn first_word(s: &str) -> &str { //函数参数为 &str let bytes = s.as_bytes(); for (i, &item) in bytes.iter().enumerate() { if item == b' ' { return &s[0..i]; } } &s[..] } fn main() { let word = first_word(&my_string[0..6]); //函数可以接收String的部分切片 let word = first_word(&my_string); //或者全部的切片 let my_string_literal = "hello world"; //这个为字符串字面量 let word = first_word(&my_string_literal[0..6]);//函数可以接受字符串变量的部分切片 let word = first_word(my_string_literal); //或者全部的切片 }
其他类型的切片
-
引用数组的一部分(数组切片
let a = [1, 2, 3, 4, 5]; let slice = &a[1..3];

(
浙公网安备 33010602011771号