c++ string 最后一个字符_一起学Rust编程「8」:字符串和切片

db80ed33eb763912c2cd6f8095378deb.png

我们已经见过了Rust的动态字符串String类型:

let mut a = String::from("hello");
a.push_str(" world");

今天再借LeetCode的题来了解一下字符串的常用操作——切片。

对String来说,切片是一种引用形式的子串,所以它的效率很高。

我们先看题目:

58. 最后一个单词的长度
给定一个仅包含大小写字母和空格 ' ' 的字符串 s,返回其最后一个单词的长度。如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词。

如果不存在最后一个单词,请返回 0 。

说明:一个单词是指仅由字母组成、不包含任何空格字符的 最大子字符串。

示例:

输入: "Hello World"
输出: 5

为了得到正确答案,需要3步操作。

  • 去除结尾的空格
  • 找到最后一个单词
  • 得到单词长度

其中第一步可以用String的trim()方法。

不考虑切片,使用已经熟悉的引用和直接返回值的方法,可以得到如下的实现:

fn find_last_word(s: &String) -> String {
    let mut r = String::new();
    for c in s.chars() {
        match c {
            ' ' => r = String::new(),
            _ => r.push(c),
        }
    }
    r
}

fn length_of_last_word(s: &String) -> i32 {
    let s = String::from(s.trim());
    let last_word = find_last_word(s);
    last_word.len() as i32
}

pub fn main() {
    let s = String::from("hello world");
    let l = length_of_last_word(&s);
    println!("length of last word: {}", l);
}

这里需要改进的地方是find_last_word,因为我们使用了动态分配的字符串来保存最后一个单词。其实,为了避免额外的内存,我们可以让函数返回一个s的切片:

fn find_last_word(s: &String) -> &str {
    let mut begin = 0;
    for (i, c) in s.char_indices() {
        if c == ' ' {
            begin = i + 1;
        }
    }
    &s[begin..]
}

这里的返回类型,&str,是一个不可变的字符串切片。它实际上引用的是String内的一个数据片段。这也意味着切片的有效期必须不能超过原始数据。

可变的切片对应的类型是&mut str,语法上也用mut关键字来区分(注意b的类型——可变变量和可变切片是相互独立的概念):

let s = String::from("hello");
let mut t = String::from("world");

let a = &s[0..1];
let b = &mut t[2..3];

由于一个切片本质也是对数据的借用,所以必须遵循借用的规则:

  • 如果已经创建了切片,那么String本身不能再被可写借用
  • 可写的切片跟其他切片或借用也不能并存

简单来说,Rust想要保证的只有两个核心的约定:一是引用和切片背后的数据不能过早的失效,二是同一时刻的数据访问方式必须是安全的(只有最多一个写者,或者只有多个读者但是没有写者)。如果碰到了跟借用有关的编译错误,就要结合编译器给出的错误提示,检查上下文里的其他切片和借用,是不是违反了共存的规则或者生命周期的规则。

最后总结一下,LeetCode 58完整的答案如下:

fn find_last_word(s: &String) -> &str {
    let mut begin = 0;
    for (i, c) in s.char_indices() {
        if c == ' ' {
            begin = i + 1;
        }
    }
    &s[begin..]
}

pub fn length_of_last_word(s: &String) -> i32 {
    let s = String::from(s.trim());
    let last_word = find_last_word(&s);
    last_word.len() as i32
}

pub fn main() {
    let s = String::from("a ");
    let l = length_of_last_word(&s);
    println!("length of last word: {}", l);
}

d6177a8456e51885a806a2943d345367.png

关注红小豆,一起学习Rust开发。欢迎点赞,转发,收藏!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值