如何解决如何在 Rust 中更改字符串中特定索引处的字符?
我正在尝试更改字符串中特定索引处的单个字符,但我不知道如何进行生锈。例如,如何将“hello world”中的第 4 个字符更改为“x”,使其成为“helxo world”?
解决方法
最简单的方法是像这样使用 replace_range()
方法:
let mut hello = String::from("hello world");
hello.replace_range(3..4,"x");
println!("hello: {}",hello);
输出:hello: helxo world
(Playground)
请注意,如果要替换的范围不在 UTF-8 代码点边界上开始和结束,这将导致恐慌。例如。这会引起恐慌:
let mut hello2 = String::from("hell? world");
hello2.replace_range(4..5,"x"); // panics because ? needs more than one byte in UTF-8
如果你想替换第 n 个 UTF-8 代码点,你必须这样做:
pub fn main() {
let mut hello = String::from("hell? world");
hello.replace_range(
hello
.char_indices()
.nth(4)
.map(|(pos,ch)| (pos..pos + ch.len_utf8()))
.unwrap(),"x",);
println!("hello: {}",hello);
}
,
在 Rust 中表示字符串的标准方式是将连续的字节范围编码为 UTF-8 字符串。 UTF-8 代码点的长度可以从 1 到 4 个字节,因此通常您不能简单地将一个 UTF-8 代码点替换为另一个,因为长度可能会发生变化。你也不能做简单的指针算术来索引 Rust String
到第 n 个字符,因为再次代码点编码可以是 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,c)| if i == idx { newchar } else { c }).collect()
}
fn replace_nth_char_ascii(s: &mut str,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,world!");
}
请记住,idx
中的 replace_nth_char_ascii
参数不是字符索引,而是字节索引。如果字符串前面有任何多字节字符,则字节索引和字符索引将不对应。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。