Rust的切片

我爱海鲸 2024-01-27 13:57:14 rust学习

简介切片

1、切片

Rust的另外一种不持有所有权的数据类型:切片(slice)

我们先来做一道题:

编写一个函数,它接收字符串作为参数

返回它在这个字符串里找到的第一个单词

如果函数没找到任何空格,那么整个字符串就被返回

fn main() {
    let mut s = String::from("Hello World");
    let worldIndex = first_word(&s);

    println!("{}",worldIndex)
}

fn first_word(s:&String)->usize {
    let bytes = s.as_bytes();

    for (i,&item) in bytes.iter().enumerate() {
        if item == b' ' {
            return i
        }
    }
    s.len()
}

上面的代码中,我们完成了这个问题的解,但是这个程序并不完善,因为上面返回的索引后它和当前的字符串就已经没有关系了(脱离了上下文),也就是说,我可以他字符串给清空,但是返回的索引并不会改变了

针对这一问题,rust中也提出了解决的方案,它就是字符串切片

字符串切片是指向字符串中一部分内容的引用

 

fn main() {
    let mut s = String::from("Hello World");
    // 0到第5个字节(不包含5)
    let s1 = &s[0..5];
    // 0到第5个字节(不包含5)
    let s2 = &s[..5];
    // 0到第最后一个字节
    let s3 = &s[..];
}

形式:[开始索引..结束索引]

   开始索引就是切片起始位置的索引值

   结束索引是切片终止位置的下一个索引值

fn main() {
    let mut s = String::from("Hello World");
    let hello = &s[0..5];
    let world = &s[6..11];
    println!("{},{}",hello,world)
}

注意

字符串切片的范围索引必须发生在有效的UTF-8字符边界内。

如果尝试从一个多字节的字符中创建字符串切片,程序会报错并退出

如:

fn main() {
    let mut s = String::from("我爱海鲸");
    let hello = &s[0..5];
    let world = &s[6..11];
    println!("{},{}",hello,world)
}

中文是占3个字节的,这里刚好切到了它的中间,所以就报错了

下面我们来重写上面那个寻找字符串的例子

fn main() {
    let mut s = String::from("Hello World");
    let worldIndex = first_word(&s);

    // s.clear();

    println!("{}",worldIndex)
}

fn first_word(s:&String)->&str {
    let bytes = s.as_bytes();

    for (i,&item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i]
        }
    }
    &s[..]
}

符串的例子 然后我们发现没法在清空s的值了,那是因为s发生了不可变的借用,要清空s的值需要发生可变的借用,在rust中如果已经发生了不可变的借用,就无法在进行可变的借用

但是可以先发生可变的借用,在发生不可变的借用。就比如我们可以把s.clear()写在first_word函数调用的前面。

字符串字面值是切片

字符串字面值被直接存储在二进制程序中。

let s = "Hello,World!";

变量s 的类型是&str,它是一个指向二进制程序特定位置的切片

 &str是不可变引用,所以字符串字面值也是不可变的

将字符串切片作为参数传递

fn first_word(s: &String) -> &str {

有经验的Rust开发者会采用&str作为参数类型,因为这样就可以同时接收 String和 &str类型的参数了:

fn first_word(s: &str) -> &str {

使用字符串切片,直接调用该函数

使用String,可以创建一个完整的String 切片来调用该函数

定义函数时使用字符串切片来代替字符串引用会使我们的APl更加通用,且不会损失任何功能。

fn main() {
    let mut s = String::from("Hello World");
    let worldIndex = first_word(&s);


    println!("{}",worldIndex);

    let mut s = "Hello World";
    let worldIndex = first_word(&s);


    println!("{}",worldIndex);
}

fn first_word(s:&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 a = [1,2,3,4,5];
    let slice = &a[1..3];
}

 

你好:我的2025

上一篇:Rust的引用与借用

下一篇:Rust的结构体