🎃个人专栏:
🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客
🐳Java基础:Java基础_IT闫的博客-CSDN博客
🐋c语言:c语言_IT闫的博客-CSDN博客
🐟MySQL:数据结构_IT闫的博客-CSDN博客
🐠数据结构:数据结构_IT闫的博客-CSDN博客
💎C++:C++_IT闫的博客-CSDN博客
🥽C51单片机:C51单片机(STC89C516)_IT闫的博客-CSDN博客
💻基于HTML5的网页设计及应用:基于HTML5的网页设计及应用_IT闫的博客-CSDN博客
🥏python:python_IT闫的博客-CSDN博客
🐠离散数学:离散数学_IT闫的博客-CSDN博客
🥽Linux:Linux_Y小夜的博客-CSDN博客
🚝Rust:Rust_Y小夜的博客-CSDN博客
欢迎收看,希望对大家有用!
目录
🎯前言
🎯引入字符串切片
🎯用字符串切片
🎯字符串字面值
🎯前言
在引入切片之前,咱们先看一道题,编写一个函数,该函数接收一个用空格分隔单词的字符串,并返回在该字符串中找到的第一个单词。如果函数在该字符串中并未找到空格,则整个字符串就是一个单词,所以应该返回整个字符串。
可能会有人这样写
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() }
现在有了一个找到字符串中第一个单词结尾索引的方法,不过这有一个问题。我们返回了一个独立的
usize
,不过它只在&String
的上下文中才是一个有意义的数字。换句话说,因为它是一个与String
相分离的值,无法保证将来它仍然有效。然而,Rust 为这个问题提供了一个解决方法:字符串 slice。
🎯引入字符串切片
String
中一部分值的引用,它看起来像这样:let s = String::from("hello world");let hello = &s[0..5];let world = &s[6..11];
不同于整个
String
的引用,hello
是一个部分String
的引用,由一个额外的[0..5]
部分指定。可以使用一个由中括号中的[starting_index..ending_index]
指定的 range 创建一个 slice,其中starting_index
是 slice 的第一个位置,ending_index
则是 slice 最后一个位置的后一个值。对于 Rust 的
..
range 语法,如果想要从索引 0 开始,可以不写两个点号之前的值。依此类推,如果 slice 包含
String
的最后一个字节,也可以舍弃尾部的数字提醒:字符串 slice range 的索引必须位于有效的 UTF-8 字符边界内,如果尝试从一个多字节字符的中间位置创建字符串 slice,则程序将会因错误而退出。
🎯用字符串切片
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[..]
}
那个当我们获取第一个单词结尾的索引后,接着就清除了字符串导致索引就无效的 bug 吗?那些代码在逻辑上是不正确的,但却没有显示任何直接的错误。问题会在之后尝试对空字符串使用第一个单词的索引时出现。slice 就不可能出现这种 bug 并让我们更早的知道出问题了 。
Rust 不允许
clear
中的可变引用和word
中的不可变引用同时存在,因此编译失败。
🎯字符串字面值
字符串字面值被储存在二进制文件中。
let s = "Hello, world!";
这里
s
的类型是&str
:它是一个指向二进制程序特定位置的 slice。这也就是为什么字符串字面值是不可变的;&str
是一个不可变引用。字符串切片作为参数传递:
如果有一个字符串 slice,可以直接传递它。如果有一个
String
,则可以传递整个String
的 slice 或对String
的引用。
String
引用的函数使得我们的 API 更加通用并且不会丢失任何功能