Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 如何更改rust中字符串中特定索引处的字符?_String_Rust_Char - Fatal编程技术网

String 如何更改rust中字符串中特定索引处的字符?

String 如何更改rust中字符串中特定索引处的字符?,string,rust,char,String,Rust,Char,我试图更改字符串中特定索引处的单个字符,但我不知道如何更改。例如,我如何将“hello world”中的第4个字符更改为“x”,使其成为“HellXO world”?在Rust中表示字符串的标准方法是将连续的字节范围编码为UTF-8字符串。UTF-8码点的长度可以是1到4字节,因此通常不能简单地用另一个替换一个UTF-8码点,因为长度可能会改变。您也不能执行简单的指针算法来索引到第n个字符的Rust字符串,因为代码点编码的长度可以是1到4个字节 因此,一种安全但缓慢的方法是这样的,迭代源字符串的

我试图更改字符串中特定索引处的单个字符,但我不知道如何更改。例如,我如何将“hello world”中的第4个字符更改为“x”,使其成为“HellXO world”?

在Rust中表示字符串的标准方法是将连续的字节范围编码为UTF-8字符串。UTF-8码点的长度可以是1到4字节,因此通常不能简单地用另一个替换一个UTF-8码点,因为长度可能会改变。您也不能执行简单的指针算法来索引到第n个字符的Rust
字符串,因为代码点编码的长度可以是1到4个字节

因此,一种安全但缓慢的方法是这样的,迭代源字符串的字符,替换所需的字符,然后创建一个新字符串:

fn replace_nth_char(s: &str, idx: usize, newchar: char) -> String {
    s.chars().enumerate().map(|(i,c)| if i == idx { newchar } else { c }).collect()
}
但是,如果我们手动确保新旧字符都是单字节ascii,那么我们可以在O(1)中实现

fn replace_nth_char_safe(s: &str, idx: usize, newchar: char) -> String {
    s.chars().enumerate().map(|(i,c)| if i == idx { newchar } else { c }).collect()
}

fn replace_nth_char_ascii(s: &mut str, idx: usize, newchar: char) {
    let s_bytes: &mut [u8] = unsafe { s.as_bytes_mut() };
    assert!(idx < s_bytes.len());
    assert!(s_bytes[idx].is_ascii());
    assert!(newchar.is_ascii());
    // we've made sure this is safe.
    s_bytes[idx] = newchar as u8;
}
fn main() {
    let s = replace_nth_char_safe("Hello, world!", 3, 'x');
    assert_eq!(s, "Helxo, world!");
    
    let mut s = String::from("Hello, world!");
    replace_nth_char_ascii(&mut s, 3, 'x');
    assert_eq!(s, "Helxo, world!");
}
fn替换字符安全(s:&str,idx:usize,newchar:char)->String{
s、 chars().enumerate().map(|(i,c)| if i==idx{newchar}else{c}).collect()
}
fn替换字符ascii(s:&mut str,idx:usize,newchar:char){
设s_bytes:&mut[u8]=safe{s.as_bytes_mut()};
断言!(idx

请记住,
replace\n\u char\u ascii
中的
idx
参数不是字符索引,而是字节索引。如果字符串前面有任何多字节字符,则字节索引和字符索引将不对应。

最简单的方法是使用如下方法:

让mut hello=String::from(“hello world”);
您好。替换_范围(3..4,“x”);
普林顿!(“你好:{}”,你好);
输出:
hello:helxo-world
()

请注意,如果要替换的范围不在UTF-8码点边界上开始和结束,这将导致死机。例如,这会引起恐慌:


让mut hello2=String::from(“helldo do do do you seeking?OP很有可能适合字节索引,在这种情况下,
String::replace_range
String
本身提供的合适工具。@user4815162342看起来你是对的,
String::replace_range()
(将其委托给
Vec::splice
)可以替换O(1)中的范围。我能看到的唯一缺点是它使用
&str
参数作为替换,我认为这需要一个静态定义的常量替换或分配。我没有研究源代码,但我希望它在需要时重新分配,或者在传递的替换与范围大小相同的情况下进行更改。我查看了它。它是安全高效的库代码,它只在需要时分配和洗牌数据。也许答案应该提到
String::replace_range
,最好在顶部。它简单、安全(从生锈的意义上讲),高效,几乎可以肯定是OP所追求的解决方案。