跳至内容
张叶安的小站
用户工具
登录
站点工具
搜索
工具
显示页面
过去修订
反向链接
最近更改
媒体管理器
网站地图
登录
>
最近更改
媒体管理器
网站地图
您的足迹:
rust:第七章结构体与枚举
本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。
====== 第七章 结构体与枚举 ====== ===== 7.1 结构体(Struct)===== 结构体是Rust中创建自定义类型的方式,允许你将多个相关的值组合在一起。 ==== 定义结构体 ==== <code rust> struct User { username: String, email: String, sign_in_count: u64, active: bool, } </code> ==== 创建实例 ==== <code rust> let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; </code> ==== 访问字段 ==== <code rust> println!("用户名:{}", user1.username); println!("邮箱:{}", user1.email); </code> ==== 可变实例 ==== <code rust> let mut user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; user1.email = String::from("anotheremail@example.com"); </code> **注意:** Rust不允许只将某个字段标记为可变,整个实例必须是可变的。 ==== 字段初始化简写 ==== 当变量名与字段名相同时,可以简写: <code rust> fn build_user(email: String, username: String) -> User { User { email, // 等价于 email: email username, // 等价于 username: username active: true, sign_in_count: 1, } } </code> ==== 结构体更新语法 ==== <code rust> let user2 = User { email: String::from("another@example.com"), username: String::from("anotherusername567"), ..user1 // 其余字段从user1获取 }; </code> **注意:** 使用..语法会发生移动,如果user1中有被移动的值,user1将失效。 ===== 7.2 元组结构体 ===== 没有命名字段的结构体,称为元组结构体: <code rust> struct Color(i32, i32, i32); struct Point(i32, i32, i32); let black = Color(0, 0, 0); let origin = Point(0, 0, 0); </code> **访问:** <code rust> println!("R: {}, G: {}, B: {}", black.0, black.1, black.2); </code> **用途:** * 给元组起个有意义的名字 * 区分不同类型的同构数据 ===== 7.3 单元结构体 ===== 没有任何字段的结构体: <code rust> struct AlwaysEqual; let subject = AlwaysEqual; </code> **用途:** 用于实现trait而不需要存储数据。 ===== 7.4 结构体的方法 ===== ==== 定义方法 ==== <code rust> struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { self.width * self.height } fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height } } fn main() { let rect1 = Rectangle { width: 30, height: 50 }; println!("面积是{}平方像素", rect1.area()); } </code> **&self参数:** * &self:不可变借用 * &mut self:可变借用 * self:获取所有权(很少使用) ==== 关联函数 ==== 不带self参数的函数,通常用于构造函数: <code rust> impl Rectangle { fn square(size: u32) -> Rectangle { Rectangle { width: size, height: size, } } } // 使用::调用 let sq = Rectangle::square(3); </code> ==== 多个impl块 ==== <code rust> impl Rectangle { fn area(&self) -> u32 { self.width * self.height } } impl Rectangle { fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width && self.height > other.height } } </code> ===== 7.5 枚举(Enum)===== 枚举允许你定义一个类型,它的值可以是几个可能的变体之一。 ==== 定义枚举 ==== <code rust> enum IpAddrKind { V4, V6, } let four = IpAddrKind::V4; let six = IpAddrKind::V6; </code> ==== 带数据的枚举 ==== <code rust> enum IpAddr { V4(u8, u8, u8, u8), V6(String), } let home = IpAddr::V4(127, 0, 0, 1); let loopback = IpAddr::V6(String::from("::1")); </code> ==== 带命名数据的枚举 ==== <code rust> enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } </code> ==== 在枚举上定义方法 ==== <code rust> impl Message { fn call(&self) { match self { Message::Quit => println!("Quit"), Message::Move { x, y } => println!("Move to ({}, {})", x, y), Message::Write(text) => println!("Write: {}", text), Message::ChangeColor(r, g, b) => println!("Color: R{}, G{}, B{}", r, g, b), } } } let m = Message::Write(String::from("hello")); m.call(); </code> ===== 7.6 Option枚举 ===== Option是标准库中定义的最常用的枚举: <code rust> enum Option<T> { Some(T), None, } </code> **使用Option:** <code rust> let some_number = Some(5); let some_string = Some("a string"); let absent_number: Option<i32> = None; </code> **Option与null的区别:** * Rust没有null * Option<T>和T是不同的类型 * 必须处理Some和None两种情况 <code rust> let x: i8 = 5; let y: Option<i8> = Some(5); // let sum = x + y; // 错误!不能相加 </code> **处理Option:** <code rust> fn plus_one(x: Option<i32>) -> Option<i32> { match x { None => None, Some(i) => Some(i + 1), } } let five = Some(5); let six = plus_one(five); let none = plus_one(None); </code> **常用方法:** <code rust> let x: Option<i32> = Some(5); // unwrap(危险) let val = x.unwrap(); // 如果是None会panic // unwrap_or(安全) let val = x.unwrap_or(0); // None时返回默认值 // unwrap_or_else let val = x.unwrap_or_else(|| 0); // map let y = x.map(|v| v * 2); // Some(10) // is_some/is_none if x.is_some() { println!("有值"); } // if let if let Some(v) = x { println!("值是{}", v); } </code> ===== 7.7 Result枚举 ===== Result用于可能失败的操作: <code rust> enum Result<T, E> { Ok(T), Err(E), } </code> **使用Result:** <code rust> use std::fs::File; let f = File::open("hello.txt"); let f = match f { Ok(file) => file, Err(error) => { panic!("打开文件失败:{:?}", error); } }; </code> **匹配不同错误:** <code rust> use std::fs::File; use std::io::ErrorKind; let f = File::open("hello.txt"); let f = match f { Ok(file) => file, Err(error) => match error.kind() { ErrorKind::NotFound => match File::create("hello.txt") { Ok(fc) => fc, Err(e) => panic!("创建文件失败:{:?}", e), }, other_error => panic!("打开文件失败:{:?}", other_error), }, }; </code> **快捷方法:** <code rust> // unwrap(危险) let f = File::open("hello.txt").unwrap(); // expect(带自定义消息) let f = File::open("hello.txt") .expect("hello.txt应该存在"); // unwrap_or_else let f = File::open("hello.txt").unwrap_or_else(|error| { if error.kind() == ErrorKind::NotFound { File::create("hello.txt").unwrap_or_else(|error| { panic!("创建文件失败:{:?}", error); }) } else { panic!("打开文件失败:{:?}", error); } }); </code> ===== 7.8 if let和while let ===== ==== if let简化模式匹配 ==== <code rust> // match写法 let some_value = Some(3); match some_value { Some(3) => println!("是三"), _ => (), } // if let写法 if let Some(3) = some_value { println!("是三"); } </code> **带else:** <code rust> if let Some(3) = some_value { println!("是三"); } else { println!("不是三"); } </code> ==== while let ==== <code rust> let mut stack = Vec::new(); stack.push(1); stack.push(2); stack.push(3); // 弹出所有元素 while let Some(top) = stack.pop() { println!("{}", top); } </code> ===== 练习题 ===== ==== 练习题7.1:实现矩形结构体 ==== <code rust> struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { self.width * self.height } fn perimeter(&self) -> u32 { 2 * (self.width + self.height) } fn can_hold(&self, other: &Rectangle) -> bool { self.width >= other.width && self.height >= other.height } fn square(size: u32) -> Rectangle { Rectangle { width: size, height: size, } } } fn main() { let rect1 = Rectangle { width: 30, height: 50 }; let rect2 = Rectangle { width: 10, height: 40 }; let rect3 = Rectangle { width: 60, height: 45 }; println!("rect1的面积:{}", rect1.area()); println!("rect1的周长:{}", rect1.perimeter()); println!("rect1能容纳rect2:{}", rect1.can_hold(&rect2)); println!("rect1能容纳rect3:{}", rect1.can_hold(&rect3)); let sq = Rectangle::square(10); println!("正方形面积:{}", sq.area()); } </code> ==== 练习题7.2:实现链表节点 ==== <code rust> enum List { Cons(i32, Box<List>), Nil, } use List::{Cons, Nil}; fn main() { let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))); // 遍历链表 fn print_list(list: &List) { match list { Cons(val, next) => { println!("{}", val); print_list(next); } Nil => println!("结束"), } } print_list(&list); } </code> ==== 练习题7.3:实现扑克牌枚举 ==== <code rust> #[derive(Debug)] enum Suit { Hearts, Diamonds, Clubs, Spades, } #[derive(Debug)] enum Rank { Ace, Number(u8), Jack, Queen, King, } #[derive(Debug)] struct Card { suit: Suit, rank: Rank, } impl Card { fn value(&self) -> u8 { match &self.rank { Rank::Ace => 11, Rank::Number(n) => *n, Rank::Jack | Rank::Queen | Rank::King => 10, } } } fn main() { let card = Card { suit: Suit::Hearts, rank: Rank::Ace, }; println!("{:?}", card); println!("牌面值:{}", card.value()); } </code> ==== 练习题7.4:实现安全除法 ==== <code rust> fn safe_divide(a: f64, b: f64) -> Option<f64> { if b == 0.0 { None } else { Some(a / b) } } fn main() { match safe_divide(10.0, 2.0) { Some(result) => println!("结果:{}", result), None => println!("除数不能为零"), } if let Some(result) = safe_divide(10.0, 0.0) { println!("结果:{}", result); } else { println!("除数不能为零"); } } </code> ===== 本章小结 ===== 本章学习了Rust的结构体和枚举: * **结构体**:命名字段的数据结构 * 命名字段结构体 * 元组结构体 * 单元结构体 * **方法**:使用impl块为类型定义方法 * **枚举**:可以有不同类型数据的变体 * **Option<T>**:表示可能存在或不存在的值 * **Result<T, E>**:表示可能成功或失败的操作 * **if let/while let**:简化模式匹配的语法糖 结构体和枚举是Rust类型系统的核心,掌握它们对于编写Rust程序至关重要。
rust/第七章结构体与枚举.txt
· 最后更改:
2026/02/03 19:45
由
127.0.0.1
页面工具
显示页面
过去修订
反向链接
回到顶部