字符与字符串类型 #
一、字符类型 char #
1.1 char 概述 #
Rust的 char 类型代表一个Unicode标量值,占用4字节:
rust
fn main() {
let c1 = 'A';
let c2 = '中';
let c3 = '🦀';
println!("{} {} {}", c1, c2, c3);
println!("char 大小: {} 字节", std::mem::size_of::<char>());
}
1.2 字符方法 #
rust
fn main() {
let c = 'A';
// 判断方法
println!("is_alphabetic: {}", c.is_alphabetic());
println!("is_numeric: {}", c.is_numeric());
println!("is_alphanumeric: {}", c.is_alphanumeric());
println!("is_lowercase: {}", c.is_lowercase());
println!("is_uppercase: {}", c.is_uppercase());
println!("is_whitespace: {}", c.is_whitespace());
println!("is_ascii: {}", c.is_ascii());
println!("is_ascii_alphabetic: {}", c.is_ascii_alphabetic());
println!("is_ascii_digit: {}", c.is_ascii_digit());
// 大小写转换
println!("to_lowercase: {}", 'A'.to_lowercase().next().unwrap());
println!("to_uppercase: {}", 'a'.to_uppercase().next().unwrap());
}
1.3 字符与数字转换 #
rust
fn main() {
// 字符转数字
let c = '7';
if let Some(digit) = c.to_digit(10) {
println!("数字: {}", digit);
}
// 数字转字符
let n: u32 = 65;
if let Some(c) = char::from_u32(n) {
println!("字符: {}", c);
}
// ASCII转换
let c = 'A';
let ascii = c as u8;
println!("ASCII值: {}", ascii);
let from_ascii = 66 as char;
println!("ASCII 66: {}", from_ascii);
}
二、字符串切片 &str #
2.1 &str 概述 #
&str 是字符串切片,是对UTF-8编码字符串的引用:
rust
fn main() {
let s: &str = "Hello, 世界!";
println!("{}", s);
println!("字节长度: {}", s.len());
println!("字符数: {}", s.chars().count());
}
2.2 字符串字面量 #
rust
fn main() {
// 普通字符串
let s1 = "Hello";
// 多行字符串
let s2 = "第一行
第二行
第三行";
// 原始字符串(不处理转义)
let s3 = r"原始字符串\n不转义";
// 原始字符串(自定义分隔符)
let s4 = r#"包含"引号"的字符串"#;
println!("{}", s1);
println!("{}", s2);
println!("{}", s3);
println!("{}", s4);
}
2.3 字节与字符 #
rust
fn main() {
let s = "Hello, 世界!";
// 字节迭代
println!("字节:");
for b in s.bytes() {
print!("{} ", b);
}
println!();
// 字符迭代
println!("字符:");
for c in s.chars() {
print!("{} ", c);
}
println!();
}
三、String 类型 #
3.1 String 概述 #
String 是可增长的、堆分配的UTF-8字符串:
rust
fn main() {
// 创建空字符串
let mut s1 = String::new();
// 从字面量创建
let s2 = String::from("Hello");
// 使用 to_string
let s3 = "World".to_string();
// 追加内容
s1.push_str("Hello");
s1.push('!');
println!("{}", s1);
println!("{}", s2);
println!("{}", s3);
}
3.2 String 创建方式 #
rust
fn main() {
// String::new
let s1 = String::new();
// String::from
let s2 = String::from("Hello");
// to_string
let s3 = "World".to_string();
// 从字符迭代器
let s4: String = ['H', 'e', 'l', 'l', 'o'].iter().collect();
// 重复
let s5 = "Ha".repeat(3);
// with_capacity
let mut s6 = String::with_capacity(100);
s6.push_str("预分配容量");
println!("{} {} {} {} {} {}", s1, s2, s3, s4, s5, s6);
}
3.3 String 操作 #
rust
fn main() {
let mut s = String::from("Hello");
// 追加字符串
s.push_str(", World!");
println!("push_str: {}", s);
// 追加字符
s.push('!');
println!("push: {}", s);
// 插入
s.insert(5, '-');
println!("insert: {}", s);
// 删除
s.remove(5);
println!("remove: {}", s);
// 弹出最后一个字符
let last = s.pop();
println!("pop: {:?}, string: {}", last, s);
// 清空
let mut s2 = String::from("Clear me");
s2.clear();
println!("clear: '{}'", s2);
// 截断
let mut s3 = String::from("Hello World");
s3.truncate(5);
println!("truncate: {}", s3);
}
3.4 String 连接 #
rust
fn main() {
// + 运算符
let s1 = String::from("Hello, ");
let s2 = String::from("World!");
let s3 = s1 + &s2; // s1 被移动,s2 被借用
println!("+: {}", s3);
// format! 宏
let s4 = String::from("tic");
let s5 = String::from("tac");
let s6 = String::from("toe");
let s7 = format!("{}-{}-{}", s4, s5, s6);
println!("format: {}", s7);
// push_str
let mut s8 = String::from("Hello");
s8.push_str(", World");
println!("push_str: {}", s8);
}
四、字符串切片 #
4.1 索引访问 #
Rust不支持直接索引字符串(因为UTF-8编码):
rust
fn main() {
let s = "Hello";
// 正确:切片
let slice = &s[0..2];
println!("切片: {}", slice);
// 错误:直接索引
// let c = s[0]; // 编译错误
}
4.2 UTF-8 注意事项 #
rust
fn main() {
let s = "你好";
// 每个中文字符占3字节
println!("字节长度: {}", s.len()); // 6
// 正确切片
let hello = &s[0..3];
println!("第一个字: {}", hello);
// 错误切片(会在运行时panic)
// let invalid = &s[0..2]; // panic: byte index 2 is not a char boundary
}
4.3 安全访问 #
rust
fn main() {
let s = "你好世界";
// 使用 chars() 获取字符
let chars: Vec<char> = s.chars().collect();
println!("第一个字符: {}", chars[0]);
// 使用 get 方法
if let Some(c) = s.chars().next() {
println!("第一个字符: {}", c);
}
// 按字符索引切片
let indices: Vec<usize> = s.char_indices().map(|(i, _)| i).collect();
if indices.len() >= 2 {
let first_char = &s[indices[0]..indices[1]];
println!("第一个字符: {}", first_char);
}
}
五、字符串遍历 #
5.1 字符遍历 #
rust
fn main() {
let s = "Hello, 世界!";
// 遍历字符
for c in s.chars() {
println!("字符: {}", c);
}
// 获取字符向量
let chars: Vec<char> = s.chars().collect();
println!("{:?}", chars);
}
5.2 字节遍历 #
rust
fn main() {
let s = "Hello";
for b in s.bytes() {
println!("字节: {}", b);
}
}
5.3 字符索引遍历 #
rust
fn main() {
let s = "Hello, 世界!";
for (index, c) in s.char_indices() {
println!("索引 {}: 字符 {}", index, c);
}
}
5.4 行遍历 #
rust
fn main() {
let s = "第一行\n第二行\n第三行";
for line in s.lines() {
println!("行: {}", line);
}
}
六、字符串搜索与替换 #
6.1 搜索 #
rust
fn main() {
let s = "Hello, World!";
// contains
println!("包含 'World': {}", s.contains("World"));
// starts_with / ends_with
println!("以 'Hello' 开头: {}", s.starts_with("Hello"));
println!("以 '!' 结尾: {}", s.ends_with("!"));
// find
if let Some(pos) = s.find("World") {
println!("'World' 位置: {}", pos);
}
// matches
let s2 = "hello hello hello";
let count = s2.matches("hello").count();
println!("'hello' 出现次数: {}", count);
}
6.2 替换 #
rust
fn main() {
let s = "I like cats. Cats are cute.";
// replace
let s1 = s.replace("cats", "dogs");
println!("replace: {}", s1);
// replacen
let s2 = s.replacen("cats", "dogs", 1);
println!("replacen: {}", s2);
// replace_range
let mut s3 = String::from("Hello World");
s3.replace_range(6..11, "Rust");
println!("replace_range: {}", s3);
}
七、字符串分割 #
7.1 split #
rust
fn main() {
let s = "apple,banana,orange";
// 按分隔符分割
for part in s.split(',') {
println!("{}", part);
}
// 收集为向量
let parts: Vec<&str> = s.split(',').collect();
println!("{:?}", parts);
// 按空白分割
let s2 = "hello world rust";
let words: Vec<&str> = s2.split_whitespace().collect();
println!("{:?}", words);
}
7.2 其他分割方法 #
rust
fn main() {
let s = "hello world";
// split_once
if let Some((first, rest)) = s.split_once(' ') {
println!("第一部分: {}", first);
println!("剩余部分: {}", rest);
}
// split_at
let (left, right) = s.split_at(5);
println!("左边: {}, 右边: {}", left, right);
// lines
let s2 = "第一行\n第二行\n第三行";
let lines: Vec<&str> = s2.lines().collect();
println!("{:?}", lines);
}
八、字符串修剪 #
rust
fn main() {
let s = " Hello, World! ";
// trim
println!("trim: '{}'", s.trim());
// trim_start / trim_end
println!("trim_start: '{}'", s.trim_start());
println!("trim_end: '{}'", s.trim_end());
// trim_matches
let s2 = "***Hello***";
println!("trim_matches: '{}'", s2.trim_matches('*'));
// trim_start_matches / trim_end_matches
println!("trim_start_matches: '{}'", s2.trim_start_matches('*'));
println!("trim_end_matches: '{}'", s2.trim_end_matches('*'));
}
九、String 与 &str 转换 #
9.1 &str 转 String #
rust
fn main() {
let s: &str = "Hello";
// to_string
let s1 = s.to_string();
// String::from
let s2 = String::from(s);
// to_owned
let s3 = s.to_owned();
println!("{} {} {}", s1, s2, s3);
}
9.2 String 转 &str #
rust
fn main() {
let s = String::from("Hello");
// 自动解引用
let slice: &str = &s;
// 作为函数参数
fn takes_str(s: &str) {
println!("{}", s);
}
takes_str(&s);
takes_str(&s[..]);
}
十、实践示例 #
10.1 字符串统计 #
rust
fn main() {
let text = "Hello, 世界! 123";
let mut letters = 0;
let mut digits = 0;
let mut spaces = 0;
let mut others = 0;
for c in text.chars() {
if c.is_alphabetic() {
letters += 1;
} else if c.is_numeric() {
digits += 1;
} else if c.is_whitespace() {
spaces += 1;
} else {
others += 1;
}
}
println!("字母: {}", letters);
println!("数字: {}", digits);
println!("空白: {}", spaces);
println!("其他: {}", others);
}
10.2 反转字符串 #
rust
fn main() {
let s = "Hello, 世界!";
// 反转字符
let reversed: String = s.chars().rev().collect();
println!("反转: {}", reversed);
}
10.3 首字母大写 #
rust
fn main() {
let s = "hello world";
let result: String = s.split_whitespace()
.map(|word| {
let mut chars = word.chars();
match chars.next() {
Some(c) => c.to_uppercase().chain(chars).collect(),
None => String::new(),
}
})
.collect::<Vec<_>>()
.join(" ");
println!("{}", result);
}
十一、总结 #
本章学习了:
char类型和Unicode支持&str字符串切片String可增长字符串- 字符串操作方法
- UTF-8编码注意事项
- 字符串搜索、替换、分割
Rust的字符串系统设计保证了UTF-8编码的正确性。下一章,我们将学习运算符。
最后更新:2026-03-27