Rust 使用函数就地编辑字符串

Rust 使用函数就地编辑字符串,rust,lifetime,Rust,Lifetime,我试图通过将字符串传递给mutate()来在位编辑字符串,请参见下文 简化示例: fn mutate(string: &mut &str) -> &str { string[0] = 'a'; // mutate string string } fn do_something(string: &str) { println!("{}", string); } fn main() { let string = "Hello,

我试图通过将字符串传递给mutate()来在位编辑字符串,请参见下文

简化示例:

fn mutate(string: &mut &str) -> &str {
    string[0] = 'a'; // mutate string
    string
}

fn do_something(string: &str) {
    println!("{}", string);
}

fn main() {
    let string = "Hello, world!";
    loop {
        string = mutate(&mut string);
        do_something(string);
    }
}
但我得到以下编译错误:

main.rs:1:33: 1:37 error: missing lifetime specifier [E0106]
main.rs:1 fn mutate(string: &mut &str) -> &str {
                                          ^~~~
main.rs:1:33: 1:37 help: this function's return type contains a borrowed value, but the signature does not say which one of `string`'s 2 elided lifetimes it is borrowed from
main.rs:1 fn mutate(string: &mut &str) -> &str {
                                          ^~~~

为什么会出现此错误?如何实现我的目标?

您根本无法更改字符串片段
&mut&str
无论如何都不是合适的类型,因为它实际上是指向不可变切片的可变指针。所有的字符串片段都是不可变的

在Rust中,字符串是有效的UTF-8序列,UTF-8是可变宽度编码。因此,通常更改字符可能会更改字符串的长度(以字节为单位)。这不能用切片来完成(因为切片总是有固定的长度),这可能会导致重新分配所拥有的字符串。此外,在99%的情况下,更改字符串中的字符并不是您真正想要的

要使用unicode代码点执行所需操作,您需要执行以下操作:

fn replace_char_at(s: &str, idx: uint, c: char) -> String {
    let mut r = String::with_capacity(s.len());
    for (i, d) in s.char_indices() {
        r.push(if i == idx { c } else { d });
    }
    r
}
但是,这具有
O(n)
效率,因为它必须遍历原始切片,而且对于复杂字符也无法正常工作-它可能会替换字母,但留下重音,反之亦然

更正确的文本处理方法是迭代通过grapheme集群,它将正确地使用变音符号和其他类似的东西(主要是):

模块中也有一些对纯ASCII字符串的支持,但可能很快就会进行改革。无论如何,这就是它的使用方式:

fn replace_ascii_char_at(s: String, idx: uint, c: char) -> String {
    let mut ascii_s = s.into_ascii();
    ascii_s[idx] = c.to_ascii();
    String::from_utf8(ascii_s.into_bytes()).unwrap()
}

如果
s
包含非ASCII字符或
c
不是ASCII字符,它会死机。

您怎么会认为
&str
String
实现
索引输出
?Unicode比这要复杂得多,因此为了避免错误,他们不这样做。我不知道如何实现你想做的事情,但…可能是我的C背景,使我想索引字符串。我知道这是不可能的生锈?我需要使用循环吗?假设我只想编辑字符串中的第100个字符,我需要在前99个字符上循环,然后才能编辑第100个字符?
fn replace_ascii_char_at(s: String, idx: uint, c: char) -> String {
    let mut ascii_s = s.into_ascii();
    ascii_s[idx] = c.to_ascii();
    String::from_utf8(ascii_s.into_bytes()).unwrap()
}