====== 字符串与集合类型 ======
===== 字符串类型 =====
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 =====
''Vec'' 是动态可增长的数组。
==== 创建和修改 ====
fn main() {
// 创建方式
let mut v1: Vec = 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 =====
==== 创建和操作 ====
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);
}
}
===== 本章小结 =====
* ''&str'' 是字符串切片,''String'' 是可增长的堆字符串
* Rust 字符串是 UTF-8 编码,不支持直接索引
* ''Vec'' 动态数组,''vec!'' 宏方便创建
* ''HashMap'' 哈希表,''entry API'' 方便处理键是否存在
* 集合在遍历时要注意所有权和借用规则