IB-Rust-字符串
字符串的定义
字符串是由字符组成的连续集合
Rust 中的字符是 Unicode 类型,因此每个字符占据 4 字节内存空间,但字符串是 UTF-8 编码,也就是字符串中的字符所占的字节数是变化的(1~4)
比如,对于“hello 中国”来说,utf8 编码为:
1 | h e l l o _ 中 国 |
str
str 是 Rust 的一个基础类型,本质是一个字节数组[u8]
str 或 [u8] 类型的值存放在内存:可能是堆,可能是栈,还可能硬编码进可执行程序
字符串字面量
字符串字面量是 str 类型,在编译时就知道其内容,其字面值文本被直接硬编码进可执行程序
在存储了该字符串之后,需要通过切片引用 &str 来访问它
&str是一种不可变引用,所以它没有所有权str类型是硬编码进可执行文件,无法被修改
1 | let s: &str = "hello world"; |
String
String 字符串是在程序运行得过程中动态生成的,其在 rust 中是一个复合数据类型,定义如下:
1 | pub struct String { |
这说明 String 是可改变的,并且拥有所有权
其他
除了 String 类型的字符串,Rust 的标准库还提供了其他类型的字符串,例如 OsString, OsStr, CsString 和CsStr 等
&str vs String
&str: 这是一个字符串切片,它是固定大小的,并且不能改变。
String: 这是一个可增长的、可改变的、拥有所有权的、UTF-8 编码的字符串类型。它通常用于需要改变或者增长字符串的情况。
类型转换
&str 的转换
字节数组 [u8]|Vec<u8>->&str
1 | use std::str; |
字符串字面量->[u8]
1 | let s = "hello 中国"; |
String->&str
String 转变为 &str 是无损的(性能无损,不会造成重写 malloc 或者数据移动)
&String 可以自动转换为 &str,因此在函数中,如果接收参数是 &String,通常会采用 &str 作为入参,提升数据兼容性
字符串是 UTF-8 编码,因此需要保证索引的字节刚好落在字符的边界,因为有些字符的长度超过 1 个字节
1 | let s = String::from("hello, world"); |
String的转换
字节数组 Vec<u8>->String
1 | fn main() { |
&str->String
从 &str 获得 String 是低效的,因为要重新 malloc 数据
1 | let s = String::from("hello 世界"); |
Overview
1 | &str -> String | String::from(s) or s.to_string() or s.to_owned() |
操作字符串
可变字符串 String 的修改,添加,删除等常用方法,且如果执行这些操作会修改原字符串,则字符串必须是 mut 的
追加 (Push)
- 使用
push()方法追加字符char - 使用
push_str()方法追加字符串字面量 - 两个方法都是在原有的字符串上追加,需要用
mut修饰
1 | let mut s = String::from("Hello "); |
插入 (Insert)
- 使用
insert()方法插入单个字符char - 使用
insert_str()方法插入字符串字面量 - 这俩方法需要传入两个参数,第一个参数是字符(串)插入位置的索引,索引从 0 开始计数;第二个参数是要插入的字符(串),注意不要越界
- 两个方法都是在原有的字符串上追加,需要用
mut修饰
1 | let mut s = String::from("Hello rust!中文"); |
替换 (Replace)
replace
replace()方法接收两个参数,第一个参数是要被替换的字符串,第二个参数是新的字符串- 该方法会替换所有匹配到的字符串
- 该方法返回一个新的字符串,而不是操作原来的字符串,所以不需要 mut 修饰
1 | let s = String::from("I like rust. Learning rust is my favorite!"); |
replacen
方法接收三个参数,前两个参数与 replace() 方法一样,第三个参数则表示替换的个数
1 | let s = "I like rust. Learning rust is my favorite!"; |
replace_range
replace_range接收两个参数,第一个参数是要替换字符串的范围(Range),第二个参数是新的字符串- 该方法是直接操作原来的字符串,需要使用
mut修饰 - 如果range的范围大于/小于新字符串长度会怎样?
- 参数的位置需要在合法的字符边界
1 | let mut s = String::from("hello rust 中国"); |
删除 (Delete)
pop
- 删除并返回字符串的最后一个字符
- 其返回值是一个
Option类型,如果字符串为空,则返回None - 该方法直接操作原来的字符串,需要用
mut修饰
1 | let mut s = String::from("中文!"); |
remove
- 其返回值是删除位置的字符串
- 接收一个参数,表示该字符起始索引位置
- 参数的位置需要在合法的字符边界
- 该方法直接操作原来的字符串,需要用
mut修饰
1 | fn main() { |
truncate
- 删除字符串中从指定位置开始到结尾的全部字符
- 参数的位置需要在合法的字符边界
- 该方法是直接操作原来的字符串,需要用
mut修饰
1 | let mut s = String::from("测试truncate"); |
clear
- 清空字符串
- 该方法直接操作原来的字符串,需要用
mut修饰
1 | let mut s = String::from("string clear"); |
连接 (Concatenate)
使用 Add()
add() 方法的第二个参数必须为字符串切片引用(Slice)类型
1 | use std::ops::Add; |
使用 + 或者 += 连接字符串
之所以可以直接 + 是因为 Add 实现了 + 的 trait
1 | let s = String::from("hello "); |
关于自动解引用
std::String -> &str 没有任何成本,反过来则需要重新申请空间
所以在定义使用字符串的函数的时候,优先定义成字符串切片的类型
关于所有权移动
- 无论是 + 还是 add 都发生了所有权移动
1 | let s = String::from("hello "); |
使用 format! 连接字符串
format!的用法与println!的用法类似
1 | let s1 = "hello"; |
Rust 手册 String 相关的函数
https://doc.rust-lang.org/std/string/struct.String.html#
字符串转义
可以通过转义的方式 \ 输出 ASCII 和 Unicode 字符。
1 | // 通过 \ + 字符的十六进制表示,转义输出一个字符 |
原样输出
1 | println!("{}", "hello \\x52\\x75\\x73\\x74"); |
- Title: IB-Rust-字符串
- Author: Gabrielle
- Created at : 2025-05-23 14:37:53
- Updated at : 2025-05-24 21:04:19
- Link: https://zoella-w.github.io/2025/05/23/67-IB-Rust-字符串/
- License: This work is licensed under CC BY-NC-SA 4.0.