实战总结
> 综合练习本章各类型知识,通过实战示例建立 Rust 类型系统的完整认知。
完整示例
示例 1:学生信息管理系统
rust
▶ Runfn main() {
// 使用元组存储学生信息
type Student = (u32, String, u8, f64); // (学号,姓名,年龄,成绩)
let students: Vec<Student> = vec![
(1, String::from("张三"), 20, 95.5),
(2, String::from("李四"), 21, 87.0),
(3, String::from("王五"), 19, 92.3),
];
println!("╔════════════════════════════════════╗");
println!("║ 学生信息表 ║");
println!("╠════════════════════════════════════╣");
for (id, name, age, score) in &students {
println!("║ 学号:{:04} │ {:6} │ {:2}岁 │ {:5.1} ║",
id, name, age, score);
}
println!("╚════════════════════════════════════╝");
// 计算平均分
let total: f64 = students.iter().map(|(_, _, _, score)| score).sum();
let average = total / students.len() as f64;
println!("平均分:{:.2}", average);
}示例 2:温度数据分析
rust
▶ Runfn main() {
// 一周温度(摄氏度)
let temperatures: [f64; 7] = [22.5, 25.0, 19.8, 23.1, 26.4, 28.0, 24.5];
println!("本周温度分析");
println!("{:=<40}", "");
// 打印每天温度
let days = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
for (day, temp) in days.iter().zip(temperatures.iter()) {
println!("{}: {:.1}°C", day, temp);
}
// 统计
let max = temperatures.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
let min = temperatures.iter().cloned().fold(f64::INFINITY, f64::min);
let sum: f64 = temperatures.iter().sum();
let avg = sum / temperatures.len() as f64;
println!("{:=<40}", "");
println!("最高温度:{:.1}°C", max);
println!("最低温度:{:.1}°C", min);
println!("平均温度:{:.1}°C", avg);
println!("温差:{:.1}°C", max - min);
}示例 3:简单密码验证器
rust
▶ Runfn main() {
let passwords: Vec<&str> = vec![
"123456", // 太弱
"Abc123!@#", // 强
"password", // 太弱
"MyP@ssw0rd", // 强
"abcdefgh", // 太弱
];
println!("密码强度检查");
println!("{:-<40}", "");
for pwd in &passwords {
let strength = check_password(pwd);
println!("{:12} → {}", pwd, strength);
}
}
fn check_password(password: &str) -> &str {
let mut score = 0;
// 长度检查
if password.len() >= 8 {
score += 1;
}
if password.len() >= 12 {
score += 1;
}
// 包含大写字母
if password.chars().any(|c| c.is_uppercase()) {
score += 1;
}
// 包含数字
if password.chars().any(|c| c.is_numeric()) {
score += 1;
}
// 包含特殊字符
if password.chars().any(|c| !c.is_alphanumeric()) {
score += 1;
}
match score {
0..=2 => "弱",
3..=4 => "中等",
5 => "强",
_ => "非常强",
}
}调试技巧
使用 dbg! 宏调试类型
rust
▶ Runfn main() {
let s = String::from("hello");
// dbg! 可以打印表达式和值
let doubled = dbg!(s.len() * 2);
// 打印类型信息
println!("类型:{:?}", std::any::type_name_of_val(&s));
// 打印内存大小
println!("String 大小:{} 字节", std::mem::size_of::<String>());
println!("&str 大小:{} 字节", std::mem::size_of::<&str>());
println!("char 大小:{} 字节", std::mem::size_of::<char>());
}格式化输出类型
rust
▶ Runfn main() {
let num: i32 = 42;
// {:?} - 调试格式
println!("调试格式:{:?}", num);
// {:#?} - 美化调试格式
let vec = vec![1, 2, 3];
println!("美化格式:{:#?}", vec);
// {:p} - 打印指针地址
let s = String::from("hello");
println!("String 数据地址:{:p}", s.as_str());
// {:b}, {:x}, {:o} - 二进制,十六进制,八进制
println!("二进制:{:b}", num);
println!("十六进制:{:x}", num);
println!("八进制:{:o}", num);
}常见错误
错误 1:类型不匹配
rust
▶ Runfn main() {
// ❌ 错误:300 超出 i8 范围
// let x: i8 = 300;
// ✅ 正确:使用更大的类型
let x: i16 = 300;
// ❌ 错误:类型不匹配
// let y: i32 = x; // i16 不能自动转 i32
// ✅ 正确:显式转换
let y: i32 = x as i32;
}错误信息:
error[E0308]: mismatched types
--> src/main.rs:3:18
|
3 | let x: i8 = 300;
| -- ^^^ expected `i8`, found integer
| |
| expected due to this错误 2:整数溢出(调试模式 panic)
rust
▶ Runfn main() {
let x: u8 = 255;
// ❌ 这会在调试模式下 panic
// let y = x + 1;
// ✅ 安全处理
let y = x.checked_add(1).unwrap_or(0);
println!("y = {}", y);
}错误信息:
thread 'main' panicked at 'attempt to add with overflow'错误 3:数组越界
rust
▶ Runfn main() {
let arr = [1, 2, 3];
// ❌ 这会 panic
// let x = arr[10];
// ✅ 安全访问
match arr.get(10) {
Some(val) => println!("{}", val),
None => println!("索引超出范围"),
}
}错误信息:
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 10'错误 4:混淆 String 和&str
rust
▶ Runfn main() {
let s1: String = String::from("hello");
let s2: &str = "world";
// ❌ 错误:类型不匹配
// let combined: &str = &s1 + s2; // String + &str 不能直接得到&str
// ✅ 正确:得到 String
let combined: String = s1 + &s2;
println!("{}", combined);
// 或者使用 format!
let s3 = String::from("hello");
let s4 = format!("{} {}", s3, "world");
println!("{}", s4);
}错误 5:试图索引 String
rust
▶ Runfn main() {
let s = String::from("你好");
// ❌ 错误:不能通过索引访问 String 中的字符
// let first = s[0];
// ✅ 正确:使用 chars()
let first = s.chars().next().unwrap();
println!("第一个字符:{}", first);
}错误信息:
error[E0277]: the type `str` cannot be indexed by `{integer}`
--> src/main.rs:4:19
|
4 | let first = s[0];
| ^^^ string indices are ranges of `usize`练习
练习 1:类型转换
编写程序,完成以下转换:
- 将 u16 值 1000 转换为 u8
- 将 i32 值 42 转换为 f64
- 将字符'A'转换为其 Unicode 码点
练习 2:数组操作
创建一个包含 10 个整数的数组,实现:
- 计算所有元素的和
- 找出最大值和最小值
- 计算平均值
练习 3:字符串处理
编写函数,接受一个&str,返回:
- 单词数量(按空格分割)
- 字符数量
- 大写字母数量
练习 4:温度转换
实现温度转换器:
- 摄氏度转华氏度:F = C × 9/5 + 32
- 摄氏度转开尔文:K = C + 273.15
小结
本章我们详细学习了:
标量类型
| 类型 | 说明 | 默认 | 示例 |
|---|---|---|---|
i32 | 有符号 32 位整数 | ✅ | 42 |
u8 | 无符号 8 位整数 | 255 | |
f64 | 64 位浮点数 | ✅ | 3.14 |
bool | 布尔值 | true, false | |
char | Unicode 字符 | 'A', '中', '🦀' |
复合类型
| 类型 | 说明 | 示例 |
|---|---|---|
| 元组 | 固定长度,可不同类型 | (1, "hello", true) |
| 数组 | 固定长度,相同类型 | [1, 2, 3, 4, 5] |
String vs &str
| 特性 | String | &str |
|---|---|---|
| 所有权 | 拥有 | 借用 |
| 可变性 | 可变 | 不可变 |
| 大小 | 24 字节 | 16 字节 |
| 创建 | String::from() | 字面量 "hello" |
| 用途 | 需要修改时 | 函数参数、只读 |
关键要点
- Rust 默认整数是 i32,默认浮点数是 f64
- 类型转换用
as关键字 - 数组越界会 panic,用
get()安全访问 - String 是可增长的,&str 是切片/视图
- 不能通过索引访问 String 中的字符(因为 UTF-8 编码)
练习题
详见:练习题