字符与字符串类型 #

一、字符类型 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