📜  如何在 rust 中索引字符串(1)

📅  最后修改于: 2023-12-03 15:08:47.750000             🧑  作者: Mango

如何在 Rust 中索引字符串

Rust 中的字符串是一种比较特殊的类型,因为它既可以是一个 &str 的引用,也可以是一个 String 的拥有者。不管是哪种形式的字符串,都可以进行索引。

索引 &str

&str 是一个不可变的引用,它本质上是一个“指向 UTF-8 编码字符串的字节数组的指针加上它的长度”。因为 Rust 中的字符串都是以 UTF-8 编码的,所以我们可以直接按照字节索引字符串。不过这样做有个问题,就是一个 Unicode 字符不一定只占一个字节,可能是两个、三个、四个甚至更多。所以,如果我们使用字节索引获取 Unicode 字符,有可能会截取它的一部分,导致字符串解析错误。

所以,我们一般不会用字节索引 &str,而是可以通过 chars() 方法得到一个包含 char 的迭代器,然后进行操作:

fn main() {
    let s = "Rust 中的字符串";
    for c in s.chars() {
        println!("{}", c);
    }
}

这样,就可以顺利地得到每个字符。如果要访问第 i 个字符,可以调用 nth(i) 方法:

fn main() {
    let s = "Rust 中的字符串";
    match s.chars().nth(5) {
        Some(c) => println!("{}", c),
        None => println!("字符串太短了"),
    }
}

需要注意的是,nth() 方法返回的是一个 Option<char>,因为有可能字符串太短,没有这么多字符。

索引 String

String 是一个可变的拥有者,我们同样可以通过 chars() 的迭代器进行操作:

fn main() {
    let mut s = String::from("Rust 中的字符串");
    for c in s.chars() {
        println!("{}", c);
    }
}

但是,如果要进行改变,我们需要注意。因为 String 中的字符不一定是按照字节连续存储的,有可能会被截断。因此,如果我们直接按照 chars() 获取到的索引进行修改,有可能会破坏字符串的编码规则。可以使用 char_indices() 方法获得每个字符相对于 String 的索引位置:

fn main() {
    let mut s = String::from("Rust 中的字符串");
    for (idx, c) in s.char_indices() {
        if idx == 5 {
            match c {
                '中' => s.replace_range(5..9, "is"),
                _ => println!("该字符不是中文,无需替换"),
            }
        }
    }
    println!("{}", s);
}

这样就可以安全地进行 replace_range() 操作。

索引 slice 中的字符串

如果我们需要从一个字符串切片中取出一部分字符,只需要使用 &str 的切片即可:

fn main() {
    let s = "Rust 中的字符串";
    let sub = &s[5..9];
    println!("{}", sub);
}

这样,就可以取出 "中的字"

小结
  • &str 是一个不可变的引用,可以通过 chars() 方法来得到包含每个字符的迭代器。如果需要访问第 i 个字符,可以调用 nth(i) 方法。
  • String 是一个可变的拥有者,同样可以通过 chars() 方法来得到包含每个字符的迭代器。如果需要进行修改,需要使用 char_indices() 方法来获得每个字符相对于 String 的索引位置。
  • 切片中的字符串可以直接参考数组或向量的切片操作。