Slice类型
Slice是rust中另外一种不用获取value的ownership就能够操作数据的结构
Slice使您可以引用集合中连续的元素序列,而不是整个集合
在内存中的分配:
对比reference在内存中的分配,String slice在栈上的结构多了一个len字段,用于表示当前slice指向内存区域的大小。
问题1 :
编写一个接受字符串并返回在该字符串中找到的第一个单词的函数。 如果函数在字符串中找不到空格,则整个字符串必须是一个单词,因此应返回整个字符串。
解:一般的思路,我们将输入的字符串视为字节流,那我们只要检查当前的字节是不是空格就好了,然后返回当前字节的序号,如果没有空格就返回整个字符串的长度
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
//这里使用return语句是因为没有else语句,所以要显式的返回i值
return i;
}
}
s.len()
}
问题2:
现在我想找到第二个单词,需要封装一个新的函数second_word
解:类似问题1的解,但是因为第一个单词
fn second_word(s: &String) -> (usize, usize) {
let bytes = s.as_bytes();
let mut begin = 0;
let mut space_counter = 0;
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
space_counter = space_counter + 1;
if space_counter == 2 {
return (begin, i);
} else if space_counter == 1 {
begin = i + 1;
}
}
}
if space_counter != 1 {
return (s.len(), s.len());
} else {
return (begin, s.len());
}
}
问题3:
现在我想将这个问题扩展到一般问题,即给定一个index,我希望函数可以返回相应index的word
解:
fn match_word(s: &String, index: usize) -> (usize, usize) {
let bytes = s.as_bytes();
let mut begin = 0;
let mut space_counter = 0;
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
space_counter = space_counter + 1;
if space_counter == index {
return (begin, i);
} else if space_counter == (index - 1) {
begin = i + 1;
}
}
}
if space_counter != (index - 1) {
return (s.len(), s.len());
} else {
return (begin, s.len());
}
}
String Slices
string slice是一个指向String中部分内容的reference。
修改上面的函数使其返回的是string 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[..]
}
问题2:
fn second_word(s: &String) -> &str {
let bytes = s.as_bytes();
let mut begin = 0;
let mut space_counter = 0;
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
space_counter = space_counter + 1;
if space_counter == 2 {
return &s[begin..i];
} else if space_counter == 1 {
begin = i + 1;
}
}
}
if space_counter != 1 {
return &s[s.len()..s.len()];
} else {
return &s[begin..];
}
}
问题3
fn match_word(s: &String, index: usize) -> &str {
let bytes = s.as_bytes();
let mut begin = 0;
let mut space_counter = 0;
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
space_counter = space_counter + 1;
if space_counter == index {
return &s[begin..i];
} else if space_counter == (index - 1) {
begin = i + 1;
}
}
}
if space_counter != (index - 1) {
return &s[s.len()..];
} else {
return &s[begin..];
}
}