字符串和切片
约 942 字大约 3 分钟
2025-01-11
注意
这样定义的变量 my_name
的类型是 &str
而不是 String
fn main() {
let my_name = "Pascal";
greet(my_name);
}
fn greet(name: String) {
println!("Hello, {}!", name);
}
切片
let s = String::from("hello");
let slice = &s[0..2];
let slice = &s[..2];
这样切片的话只能切割字节,如果是中文,每一位字符占用 3 个字节
let s = String::from("你好");
let slice = &s[0..2];
这样截取的话就会报错,因为截取到了不完整的字符串,也就是开始和结束必须落在字符之间的边界位置上
当然数组等也支持切片
let a = [1, 2, 3, 4, 5];
let slice = &a[1..3];
assert_eq!(slice, &[2, 3]);
字符串字面量
字符串字面量也是切片,类型是 &str
,是一个不可变引用
let s = "Hello";
他与
let s = String::from("Hello");
是不一样的
String 和 &str 转换
fn main() {
// &str 转 String
let a = "123";
let b = a.to_string();
let c = String::from(a);
// String 转 &str
let s = String::from("hello,world!");
say_hello(&s);
say_hello(&s[..]);
say_hello(s.as_str());
}
fn say_hello(s: &str) {
println!("{}",s);
}
字符串索引
let s1 = String::from("hello");
let h = s1[0];
在 rust
中这样是不能正确读取到第一个字符的,只能使用切片的方式截取文本,不过这样并不安全,因为切片使用的是 byte
作为单位的,中文字符等会导致长度并不固定
let s1 = String::from("hello");
let h = &s1[..1];
println!("{}", h);
字符串追加
push
方法只能插入字符
push_str
方法是用来插入 &str
的
这样追加不会返回新的字符串而是影响原变量
fn main() {
let mut a = String::from("a");
a.push('b');
a.push_str("cd");
}
字符串插入
insert
insert_str
和追加规则类似
第一位传入索引值,当然一样需要注意索引需要落在边界上,不能在字符中
fn main() {
let mut s = String::from("Hello rust!");
s.insert(5, ',');
println!("插入字符 insert() -> {}", s);
s.insert_str(6, " I like");
println!("插入字符串 insert_str() -> {}", s);
}
字符串替换
替换有两种方法 replace
replacen
replacen
可以传入替换个数
替换后会返回新的变量,他和追加不同,他并不会修改原有变量
fn main() {
let string_replace = String::from("I like rust. Learning rust is my favorite!");
let new_string_replace = string_replace.replace("rust", "RUST");
dbg!(new_string_replace);
}
还有一个 replace_range
方法,他仅适用于 String
类型
他会修改原变量,所以需要可变,他会替换指定范围内的内容为指定字符串
fn main() {
let mut string_replace_range = String::from("I like rust!");
string_replace_range.replace_range(7..8, "R");
dbg!(string_replace_range);
}
字符串删除
pop
remove
truncate
clear
一共四个,他们仅限 String
类型上使用
pop
会删除最后一个字符然后返回,如果为空则会返回 None
fn main() {
let mut string_pop = String::from("rust pop 中文!");
let p1 = string_pop.pop();
let p2 = string_pop.pop();
dbg!(p1);
dbg!(p2);
dbg!(string_pop);
}
remove
传入的参数是该字符的起始位置,不能是中间的位置,会操作原有变量,但也会返回删除位置的字符串
fn main() {
let mut string_remove = String::from("测试remove方法");
println!(
"string_remove 占 {} 个字节",
std::mem::size_of_val(string_remove.as_str())
);
// 删除第一个汉字
string_remove.remove(0);
// 下面代码会发生错误
// string_remove.remove(1);
// 直接删除第二个汉字
// string_remove.remove(3);
dbg!(string_remove);
}
truncate
删除从指定位置开始到结尾的所有字符
方法也会直接操作原有变量
fn main() {
let mut string_truncate = String::from("测试truncate");
string_truncate.truncate(3);
dbg!(string_truncate);
}
clear
清空整个字符串
字符串连接
可以使用 +
或 +=
来连接字符串,但是需要右侧为切片类型
他其实就是调用了 add
方法
还有一种方法,他类似于 模板字符串
的功能
fn main() {
let s1 = "hello";
let s2 = String::from("rust");
let s = format!("{} {}!", s1, s2);
println!("{}", s);
}