目录

字符串与集合类型

字符串类型

Rust 中有两种主要的字符串类型:String&str

&str:字符串切片

&str 是对字符串数据的不可变引用,通常称为“字符串切片”。

fn main() {
    // 字符串字面量是 &str
    let s: &str = "hello";
 
    // 从 String 取切片
    let string = String::from("hello world");
    let slice = &string[0..5]; // &str 类型
}

String:可增长字符串

String 是堆上分配的、可增长的 UTF-8 字符串。

fn main() {
    // 创建 String
    let mut s1 = String::new();           // 空字符串
    let s2 = String::from("hello");       // 从字面量创建
    let s3 = "world".to_string();         // 方式二
 
    // 追加字符串
    s1.push_str("hello");  // 追加 &str
    s1.push('!');          // 追加单个字符
    println!("{}", s1);   // hello!
 
    // 拼接字符串
    let s4 = s2 + " " + &s3; // 注意:s2 被移动
    println!("{}", s4);       // hello world
 
    // 使用 format! 宏(更灵活,不转移所有权)
    let s5 = format!("{} {}", s3, s1);
    println!("{}", s5);
}

字符串索引

Rust 字符串不支持直接索引(因为 UTF-8 编码,字符长度可变):

fn main() {
    let s = String::from("你好");
 
    // let c = s[0]; // 编译错误!不能直接索引
 
    // 正确方式:
    for c in s.chars() {
        println!("{}", c); // 你, 好
    }
 
    for b in s.bytes() {
        println!("{}", b); // 228, 189, 160, 229, 165, 189
    }
}

向量 Vec<T>

Vec<T> 是动态可增长的数组。

创建和修改

fn main() {
    // 创建方式
    let mut v1: Vec<i32> = Vec::new();
    let v2 = vec![1, 2, 3, 4, 5]; // 用宏创建
 
    // 添加元素
    v1.push(10);
    v1.push(20);
    v1.push(30);
 
    // 删除末尾元素
    let last = v1.pop();  // Some(30) 或 None
 
    // 读取元素
    let third = &v2[2];           // 直接索引,越界 panic
    let third = v2.get(2);        // Option<&T>,安全
}

遍历

fn main() {
    let mut v = vec![1, 2, 3];
 
    // 不可变遍历
    for i in &v {
        println!("{}", i);
    }
 
    // 可变遍历
    for i in &mut v {
        *i *= 2; // 解引用修改
    }
}

哈希表 HashMap<K, V>

创建和操作

use std::collections::HashMap;
 
fn main() {
    let mut scores = HashMap::new();
 
    scores.insert(String::from("蓝队"), 10);
    scores.insert(String::from("红队"), 50);
 
    // 访问
    let score = scores.get("蓝队");  // Option<&i32>
    match score {
        Some(s) => println!("{}", s),
        None => println!("未找到"),
    }
 
    // 遍历
    for (key, value) in &scores {
        println!("{}: {}", key, value);
    }
}

entry API

use std::collections::HashMap;
 
fn main() {
    let mut map = HashMap::new();
    map.insert(String::from("a"), 10);
 
    // 只在键不存在时插入
    map.entry(String::from("a")).or_insert(20);
    map.entry(String::from("b")).or_insert(30);
 
    println!("{:?}", map); // {"a": 10, "b": 30}
}

本章实践:单词统计

use std::collections::HashMap;
 
fn main() {
    let text = "hello world hello rust hello everyone";
 
    let mut word_count = HashMap::new();
 
    for word in text.split_whitespace() {
        let count = word_count.entry(word.to_string()).or_insert(0);
        *count += 1;
    }
 
    for (word, count) in &word_count {
        println!("'{}': {}", word, count);
    }
}

本章小结