大家好,
欢迎来到学习rust的第8天,在前几天我已经完成了所有权、引用和其他重要概念。这将是本章的最后一集,明天我将开始学习结构体。
引言
在rust中,切片(Slices)允许你引用集合中的连续元素序列,而不是整个集合。
rust
let numbers = [1, 2, 3, 4, 5];
let slice = &numbers[1..4]; // [2, 3, 4]
[1..4]
从索引1开始,到3结束,4是排除的。[1..=4]
从索引1开始,到4结束。
可视化表示
字符串切片
rust
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()
}
这个函数以字符串作为参数,并返回第一个 空格
字符的索引。
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 s: String = String::from("Hello World");
let word_index: usize = first_word(&s); // word_index = 5
s.clear(); //现在字符串是空的
//word_index仍然是5,但是字符串是空的,因此这个值是无用的
}
第二个问题是它的实现方式。如果我们用这种实现方式获取第二个单词,我们的函数定义会是这样的
rust
fn second_word(s: &String) -> (usize, usize) {
...
}
字符串切片的工作原理与切片相同,只不过它们用在字符串上,例如:
rust
fn main() {
let s: String = String::from("Hello World");
let hello: &str = &s[0..5];
println!("{}", hello);
}
现在我们对函数和字符串切片有了基本的理解,让我们修改我们的函数。
rust
fn first_word(s: &str) -> &str {
let bytes: &[u8] = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
fn main() {
let string: &str = "Hello World!";
let word = first_word(&string);
println!("{}", word);
}
fn first_word(s: &str) -> &str {
: 定义了一个函数来查找并返回字符串切片中的第一个单词。let bytes: &[u8] = s.as_bytes();
: 将字符串切片转换为字节切片。for (i, &item) in bytes.iter().enumerate() {
: 遍历字节切片中的每个字节,跟踪其索引。if item == b' ' { return &s[0..i]; }
: 如果找到空格字符,则返回从索引0
到i
的子字符串的引用,表示第一个单词。&s[..]
: 如果未找到空格字符,则返回对原始字符串切片的引用,表示整个字符串是"第一个单词"。
为了练习,你可以创建一个函数,用这种方法获取第二个单词。祝你好运!
结论
总之,在学习Rust的第8天,我们深入了解了切片的概念。Rust中的切片允许我们引用集合中的连续元素序列,提供了对数据操作的更细粒度控制。我们探讨了如何使用数组和字符串字面量创建切片,理解了范围语法及其排他性。