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
| // pub fn strtok<'b, 'a>(s: &'b mut &'a str, delimiter: char) -> &'a str
// &'b mut: 指向字符串引用的可变引用 &mut 的生命周期
// &'a str: 字符串引用 &str 本身的生命周期
// 由于返回值只和 &str 有关, 所以可只需标注他的生命周期, 其他无关的生命周期可省略, 让编译器来自动添加
pub fn strtok<'a>(s: &mut &'a str, delimiter: char) -> &'a str {
if let Some(i) = s.find(delimiter) {
let prefix = &s[..i];
// 由于 delimiter 可以是 utf8,所以我们需要获得其 utf8 长度,
// 直接使用 len 返回的是字节长度,会有问题
let suffix = &s[(i + delimiter.len_utf8())..];
*s = suffix;
prefix
} else { // 如果没找到,返回整个字符串,把原字符串指针 s 指向空串
let prefix = *s;
*s = "";
prefix
}
}
fn main() {
let s = "hello world".to_owned(); // str
let mut s1 = s.as_str(); // &str
let hello = strtok(&mut s1, ' '); // 访问 s1 的可变引用
println!("hello is: {}, s1: {}, s: {}", hello, s1, s); // 访问 s1 的不可变引用
// print: "hello is: hello, s1: world, s: hello world"
}
// 注意!, strtok 生命周期标注不能写成如下样子
// 会导致 print s1(访问 s1 的不可变引用) 时报错:
// - cannot borrow `s1` as immutable because it is also borrowed as mutable
// 这是因为这样标注就表示可变借用 &mut 和 返回值的生命周期一样了, 导致这个引用的生命周期在函数结束后还没有结束
// 这样在 print s1 时, 就会发生可变引用和不可变引用同时存在的情况, 导致报错
/*
let hello = strtok(&mut s1, ' '); // 访问 s1 的可变引用
// 此时 s1 的生命周期 == hello 的生命周期
println!("hello is: {}, s1: {}, s: {}", hello, s1, s); // 访问 s1 的不可变引用
*/
pub fn strtok<'a>(s: &'a mut &str, delimiter: char) -> &'a str
|