Logo

Rust 字符串

Rust 字符串

一、字符串类型体系

1.1 核心字符串类型

&str(字符串切片): • 不可变引用类型,可指向字符串字面量或String的切片 • 编译时确定大小,存储在栈或程序的只读数据段 • 类型表示为&'static str(字面量)或&str(动态切片)

String: • 可变、堆分配的UTF-8字符串类型 • 所有权类型,支持动态增长和修改 • 底层存储为Vec<u8>的包装类型

1.2 其他字符串类型

OsString/OsStr:处理操作系统原生格式的字符串 • CString/CStr:用于C语言交互的null-terminated字符串 • PathBuf/Path:专用于文件路径处理的类型

二、字符串切片机制

2.1 切片基础

• 语法:[start..end](前闭后开区间) • 内存结构:存储起始指针和长度(字节长度) • 有效索引必须落在UTF-8字符边界

let s = String::from("中国人");
let valid = &s[0..3]; // "中"
// let invalid = &s[0..2]; 运行时panic

2.2 切片特性

• 零拷贝:不分配新内存 • 生命周期:依赖原字符串数据 • 通用性:同样适用于数组等连续集合

let arr = [1,2,3,4,5];
let slice = &arr[1..3]; // &[i32]类型

三、字符串操作详解

3.1 创建与转换

方法说明
String::from("str")字面量转String
"str".to_string()同前,语法糖形式
s.as_str()String转&str
s[..]显式切片转换
&str.to_string()字面量转string

3.2 修改操作

追加

let mut s = String::new();
s.push('€');      // 追加字符
s.push_str("20");// 追加字符串

插入

s.insert(5, '!');     // 插入字符
s.insert_str(0, "Hi ");// 插入字符串

替换

let s1 = s.replace("Hi", "Hello"); // 全量替换
s.replacen("l", "L", 1);          // 替换指定次数
s.replace_range(0..2, "HE");      // 范围替换

3.3 删除操作

方法行为示例
pop()移除最后一个字符返回Options.pop().unwrap()
remove(n)移除并返回第n字节的字符s.remove(0)
truncate(n)保留前n字节s.truncate(3)
clear()等价truncate(0)s.clear()

3.4 字符串连接

+运算符

let s1 = String::from("Hello");
let s2 = String::from("Rust");
let s3 = s1 + &s2;  // s1所有权转移

format!宏

let s = format!("{}-{}", 2024, "year");
    string_slice("blue");
    string("red".to_string());
    string(String::from("hi"));
    string("rust is fun!".to_owned());
    string_slice("nice weather".into());
    string(format!("Interpolation {}", "Station"));
    string_slice(&String::from("abc")[0..1]);
    string_slice("  hello there ".trim());
    string("Happy Monday!".to_string().replace("Mon", "Tues"));
    string("mY sHiFt KeY iS sTiCkY".to_lowercase());

四、UTF-8处理机制

4.1 编码特性

• 动态字节长度:1-4字节/字符 • 禁止直接索引访问:

let s = "नमस्ते";
// let c = s[0]; 编译错误

4.2 遍历方法

字符级遍历

for c in "中国人".chars() { /* char类型处理 */ }

字节级遍历

for b in "中国人".bytes() { /* u8类型处理 */ }

4.3 子串处理

• 推荐使用utf8_slice库:

utf8_slice::slice(s, 1, 3); // 安全字符切片

五、内存管理机制

5.1 所有权模型

String:拥有堆内存的所有权 • &str:借用数据,无所有权

5.2 RAII机制

• 自动内存回收:

{
    let s = String::from("temp"); // 分配内存
} // 自动调用drop释放内存

六、典型错误场景

6.1 类型不匹配

fn greet(name: String) {}
let s = "Rust";
// greet(s); 错误!需s.to_string()

6.2 无效切片

let s = "αβγ";
// let sub = &s[0..1]; 运行时panic

6.3 借用冲突

let mut s = String::from("hello");
let slice = &s[..];
// s.clear(); 编译错误:存在不可变借用

七、最佳实践

  1. 优先使用&str类型作为函数参数
  2. 需要修改时选择String类型
  3. 避免直接字节索引操作
  4. 处理多字节字符时使用chars()遍历
  5. 复杂字符串操作使用专用库(如regex、utf8_slice)

通过深入理解Rust的字符串系统,开发者可以避免常见陷阱,编写出安全高效的字符串处理代码。字符串设计的核心差异源于Rust的内存安全理念,在保证安全性的同时兼顾了灵活性。

© 2025 All rights reservedBuilt with Flowershow Cloud

Built with LogoFlowershow Cloud