9、初识Rust – slice类型

目录 编程

slice允许开发者使用集合中一段连续的元素序列,而不用引用整个集合。slice是一类引用,所以它没有所有权。

理解slice之前,我们先来尝试实现一个功能,提取字符串中某字符开始后的指定内容。

fn main() {
    let a = String::from("hello,world");
    for (i,&item) in a.as_bytes().into_iter().enumerate() {
        println!("{item}");
    }
}

如上,声明一个变量a,并附值hello,world。

然后将a转换为字节数组,并使用 iter 创建一个迭代器。iter方法会返回集合中每一个元素,在使用enumerate包装返回的结果,然后将结果进行for遍历。

遍历索引会存放在i变量,内容会存放在 item变量。

fn main() {
    let a = String::from("hello,world");
    let b = test_function(&a);
    println!("{b}");
}

fn test_function(a: &String) -> usize {

    for (i, &item) in a.as_bytes().iter().enumerate() {
        if item == b',' {
            return i;
        };
    };

    a.len()
}

然后对item进行一个判断,遇到字符串 ( , ) 时,返回该字符串所在的位置,如果没有找到,那么就返回字符串长度。如上代码,返回 5。接下去就可以使用slice方法提取该字符后指定数量的字符串。

fn main() {
    let a = String::from("hello,world");
    let b = test_function(&a);

    let c = &a[b..{b + 2}];
    println!("{c}");
}

fn test_function(a: &String) -> usize {

    for (i, &item) in a.as_bytes().iter().enumerate() {
        if item == b',' {
            println!("{item},{i}");
            return i;
        };
    };

    a.len()
}

为什么上面没有看见slice关键字?因为slice已内置在字符串变量中,所以直接简写即可。

let a = String::from("hello,world");
let b = &a[..2]; //let b = &a[0..2];
let c = &a[2..]; //let b = &a[2..{a.len()}];

也可以像上面这样写。但是需要注意,长度如果超出字符串,则会抛出错误,所以在使用时,需要注意判断。

注意:字符串 slice range 的索引必须位于有效的 UTF-8 字符边界内,如果尝试从一个多字节字符的中间位置创建字符串 slice,则程序将会因错误而退出。出于介绍字符串 slice 的目的,本部分假设只使用 ASCII 字符集;第八章的 “使用字符串存储 UTF-8 编码的文本” 部分会更加全面的讨论 UTF-8 处理问题。