一、Rust 字符串概述
Rust 字符串是 UTF-8 编码的文本序列,提供两种主要类型:
- &str - 字符串切片(通常作为引用出现)
- String - 动态可变的、拥有所有权的字符串
二、字符串字面量 (&str)
编译时已知大小,静态分配在只读内存中
let greeting: &str = "Hello, world!";
println!("字符串字面量: {}", greeting);
三、String 类型
动态分配在堆上,可增长和修改的所有权字符串
let mut s = String::from("Hello");
s.push_str(", world!");
println!("String 类型: {}", s);
四、创建 String 的多种方式
- 创建空字符串
let empty = String::new();
println!("空字符串: '{}'", empty);
- 从字面量创建
let from_literal = String::from("初始内容");
println!("从字面量创建: {}", from_literal);
- 使用 to_string() 方法
let to_string = "另一个字符串".to_string();
println!("to_string(): {}", to_string);
- 使用 format! 宏
let formatted = format!("格式化 {} {}", "字符串", 123);
println!("format! 宏: {}", formatted);
五、修改 String
let mut mutable_string = String::from("Hello");
// 添加单个字符
mutable_string.push('!');
println!("添加字符后: {}", mutable_string);// 添加字符串切片
mutable_string.push_str(" World");
println!("添加字符串后: {}", mutable_string);// 在指定位置插入
mutable_string.insert_str(6, "Rust ");
println!("插入后: {}", mutable_string);
六、字符串访问和迭代
let text = String::from("Hello");// 获取第一个字符(Option<char> 类型)
if let Some(first_char) = text.chars().nth(0) {println!("第一个字符: {}", first_char);
}// 迭代所有字符
print!("字符迭代: ");
for c in text.chars() {print!("{} ", c);
}
println!();// 字符串切片(注意:基于字节索引,非ASCII字符需要小心)
let slice = &text[0..1]; // "H"
println!("切片: {}", slice);
七、Unicode 和非 ASCII 字符处理
let unicode_text = "Здравствуйте"; // 俄语"你好"
println!("Unicode 文本: {}", unicode_text);// 字符数统计(不是字节数)
let char_count = unicode_text.chars().count();
let byte_count = unicode_text.len();
println!("字符数: {}, 字节数: {}", char_count, byte_count);// 遍历 Unicode 字符
print!("Unicode 字符: ");
for c in unicode_text.chars() {print!("{} ", c);
}
println!();
八、字符串转换和操作
let original = String::from("hello");// 转换为大写(返回新字符串)
let upper = original.to_uppercase();
println!("大写: {}", upper);// 转换为小写
let lower = upper.to_lowercase();
println!("小写: {}", lower);// 字符串替换
let replaced = original.replace("he", "she");
println!("替换后: {}", replaced);// 字符串分割
let sentence = "Rust is awesome!";
let words: Vec<&str> = sentence.split_whitespace().collect();
println!("分割单词: {:?}", words);
九、&str 和 String 的关系与转换
// &str → String(需要分配内存)
let slice: &str = "切片";
let owned: String = slice.to_string();
println!("&str 转 String: {}", owned);// String → &str(零成本转换)
fn process_text(text: &str) {println!("处理文本: {}", text);
}let string_data = String::from("一些数据");
process_text(&string_data); // 自动解引用转换
十、原始字符串和转义
// 普通转义
let escaped = "包含\"引号\"和\\反斜杠";
println!("转义字符串: {}", escaped);// 原始字符串(避免转义)
let raw = r#"原始字符串: "内容" 和 \反斜杠"#;
println!("原始字符串: {}", raw);// 多级原始字符串(处理包含 # 的文本)
let complex_raw = r###"包含 # 号的 "原始" 字符串"###;
println!("复杂原始字符串: {}", complex_raw);
十一、字符串索引的注意事项
// Rust 不允许直接索引字符串(因UTF-8变长编码)
let sample = "Rust编程";// 错误:不能直接索引
// let first_char = sample[0]; // 正确方式:使用字符迭代
if let Some(first) = sample.chars().nth(0) {println!("第一个字符: {}", first);
}// 获取字符向量(注意性能开销)
let chars: Vec<char> = sample.chars().collect();
println!("字符向量: {:?}", chars);
十二、字符串连接
// 使用 + 运算符(会获取所有权)
let s1 = String::from("Hello");
let s2 = String::from(" World");
let combined = s1 + &s2; // s1 被移动,不能再使用
println!("连接后: {}", combined);// 使用 format! 宏(推荐,不会获取所有权)
let s3 = String::from("Hello");
let s4 = String::from(" World");
let formatted_combine = format!("{}{}", s3, s4);
println!("format! 连接: {}", formatted_combine);
// s3 和 s4 仍然可用
十三、实用字符串方法
let example = String::from(" Rust Programming ");// 去除首尾空白
let trimmed = example.trim();
println!("去除空白: '{}'", trimmed);// 检查是否包含子串
let contains = example.contains("Rust");
println!("包含 'Rust': {}", contains);// 查找子串位置
if let Some(pos) = example.find("Programming") {println!("'Programming' 位置: {}", pos);
}// 字符串长度(字节数)
println!("字节长度: {}", example.len());// 判断是否为空
println!("是否为空: {}", example.is_empty());
十四、总结:
- &str: 静态、不可变、零成本抽象的字符串视图
- String: 动态、可变、拥有所有权的字符串
- UTF-8 编码确保完整的 Unicode 支持
- 设计注重内存安全和性能
- 丰富的API支持各种字符串操作
性能提示:频繁的字符串修改建议使用 String,只读操作使用 &str