第8篇:结构模板——自定义数据类型 Rust中文编程

第8篇:结构模板------自定义数据类型

作者: 李金雨
联系方式: wbtm2718@qq.com
目标读者: Rust中文编程
核心理念: AI时代必须使用中文编程,母语编程阅读效率极高


1. 开篇引入

本课目标

  • 理解什么是结构模板(结构体)
  • 掌握结构体的定义方法
  • 掌握创建结构体实例的方法
  • 掌握访问和修改结构体字段的方法
  • 理解结构体的用途

生活场景引入

想象一下,你需要填写一份学生登记表,上面有姓名、年龄、性别、班级、成绩等信息。这份登记表就是一个模板,你可以用它来记录每个学生的信息。

在编程中,结构体就像这样的模板,它定义了一组相关的数据字段,你可以用它来创建具体的实例。

预期成果展示

通过这节课的学习,你将能够:

  • 定义自己的结构体
  • 创建结构体实例
  • 访问和修改结构体字段
  • 理解结构体在组织数据方面的优势

2. 概念讲解

什么是结构模板(结构体)

结构体是一种自定义的数据类型,它可以包含多个不同类型的字段。就像一个表单,包含多个输入项。

例如,我们可以定义一个学生结构体,包含姓名、年龄、成绩等字段:

rust 复制代码
fn main() {
    struct 学生 {
        姓名: String,
        年龄: i32,
        成绩: i32,
        科目列表: Vec<String>,
    }
}

为什么要用结构体

  1. 组织相关数据:将相关的数据放在一起,使代码更清晰
  2. 代码复用:可以创建多个相同类型的实例
  3. 数据封装:可以将数据和操作数据的方法放在一起
  4. 类型安全:编译器会检查结构体的字段类型

定义结构体

在Rust中,我们使用struct关键字来定义结构体:

rust 复制代码
struct 结构体名 {
    字段1: 类型1,
    字段2: 类型2,
    // 更多字段...
}

例如:

rust 复制代码
fn main() {
    // 定义一个学生结构体
    struct 学生 {
        姓名: String,
        年龄: i32,
        成绩: i32,
        科目列表: Vec<String>,
    }

    // 定义一个汽车结构体
    struct 汽车 {
        品牌: String,
        型号: String,
        颜色: String,
        速度: f64,
    }

    // 定义一个书籍结构体
    struct 书籍 {
        书名: String,
        作者: String,
        价格: f64,
        页数: i32,
    }
}

创建实例

创建结构体实例就像填写表单一样,需要为每个字段提供值:

rust 复制代码
fn main() {
    struct 学生 {
        姓名: String,
        年龄: i32,
        成绩: i32,
        科目列表: Vec<String>,
    }

    struct 汽车 {
        品牌: String,
        型号: String,
        颜色: String,
        速度: f64,
    }

    struct 书籍 {
        书名: String,
        作者: String,
        价格: f64,
        页数: i32,
    }

    // 创建学生实例
    let 学生一 = 学生 {
        姓名: String::from("张三"),
        年龄: 15,
        成绩: 95,
        科目列表: vec![String::from("数学"), String::from("英语")],
    };

    // 创建汽车实例
    let 汽车一 = 汽车 {
        品牌: String::from("丰田"),
        型号: String::from("卡罗拉"),
        颜色: String::from("白色"),
        速度: 0.0,
    };

    // 创建书籍实例
    let 书籍一 = 书籍 {
        书名: String::from("Rust编程入门"),
        作者: String::from("李金雨"),
        价格: 49.9,
        页数: 300,
    };
}

如果已经有一个实例,你可以基于它创建新的实例,只修改部分字段:

rust 复制代码
fn main() {
    struct 学生 {
        姓名: String,
        年龄: i32,
        成绩: i32,
        科目列表: Vec<String>,
    }

    let 学生一 = 学生 {
        姓名: String::from("张三"),
        年龄: 15,
        成绩: 95,
        科目列表: vec![String::from("数学")],
    };

    let 学生二 = 学生 {
        姓名: String::from("李四"),
        ..学生一 // 使用学生一的其他字段值
    };
}

访问和修改字段

访问结构体字段使用点号(.):

rust 复制代码
fn main() {
    struct 学生 {
        姓名: String,
        年龄: i32,
        成绩: i32,
        科目列表: Vec<String>,
    }

    let 学生一 = 学生 {
        姓名: String::from("张三"),
        年龄: 15,
        成绩: 95,
        科目列表: vec![],
    };

    // 访问字段
    println!("姓名:{}", 学生一.姓名);
    println!("年龄:{}岁", 学生一.年龄);
    println!("成绩:{}分", 学生一.成绩);
}

修改结构体字段需要使用mut关键字:

rust 复制代码
fn main() {
    struct 学生 {
        姓名: String,
        年龄: i32,
        成绩: i32,
        科目列表: Vec<String>,
    }

    let mut 学生一 = 学生 {
        姓名: String::from("张三"),
        年龄: 15,
        成绩: 95,
        科目列表: vec![],
    };

    // 修改字段
    学生一.成绩 = 98;
    学生一.科目列表.push(String::from("数学"));

    println!("修改后的成绩:{}分", 学生一.成绩);
    println!("科目列表:{:?}", 学生一.科目列表);
}

3. 动手实践

基础练习(必做)

  1. 创建"动物"结构体 :创建一个程序,定义动物结构体并创建实例:

    rust 复制代码
    struct 动物 {
        名称: String,
        年龄: i32,
        声音: String,
    }
    
    fn main() {
        let 猫 = 动物 {
            名称: String::from("猫咪"),
            年龄: 2,
            声音: String::from("喵喵"),
        };
        
        let 狗 = 动物 {
            名称: String::from("狗狗"),
            年龄: 3,
            声音: String::from("汪汪"),
        };
        
        println!("{}今年{}岁,叫声是{}", 猫.名称, 猫.年龄, 猫.声音);
        println!("{}今年{}岁,叫声是{}", 狗.名称, 狗.年龄, 狗.声音);
    }
  2. 创建"汽车"结构体 :创建一个程序,定义汽车结构体并修改字段:

    rust 复制代码
    struct 汽车 {
        品牌: String,
        颜色: String,
        速度: f64,
    }
    
    fn main() {
        let mut 我的汽车 = 汽车 {
            品牌: String::from("大众"),
            颜色: String::from("黑色"),
            速度: 0.0,
        };
        
        println!("我的汽车是{}牌,颜色是{},当前速度是{}km/h", 
                 我的汽车.品牌, 我的汽车.颜色, 我的汽车.速度);
        
        // 加速
        我的汽车.速度 = 60.0;
        println!("加速后,速度是{}km/h", 我的汽车.速度);
        
        // 减速
        我的汽车.速度 = 30.0;
        println!("减速后,速度是{}km/h", 我的汽车.速度);
    }
  3. 创建"书籍"结构体 :创建一个程序,定义书籍结构体并基于现有实例创建新实例:

    rust 复制代码
    struct 书籍 {
        书名: String,
        作者: String,
        价格: f64,
        页数: i32,
    }
    
    fn main() {
        let 书籍一 = 书籍 {
            书名: String::from("Rust编程入门"),
            作者: String::from("李金雨"),
            价格: 49.9,
            页数: 300,
        };
        
        // 基于书籍一创建书籍二
        let 书籍二 = 书籍 {
            书名: String::from("Rust高级编程"),
            价格: 59.9,
            ..书籍一
        };
        
        println!("书籍一:{},作者:{},价格:{}元,页数:{}页", 
                 书籍一.书名, 书籍一.作者, 书籍一.价格, 书籍一.页数);
        println!("书籍二:{},作者:{},价格:{}元,页数:{}页", 
                 书籍二.书名, 书籍二.作者, 书籍二.价格, 书籍二.页数);
    }

进阶练习(选做)

  1. 创建"点"结构体 :创建一个程序,定义点结构体并计算两点之间的距离:

    rust 复制代码
    struct 点 {
        x: f64,
        y: f64,
    }
    
    fn 计算距离(点一: &点, 点二: &点) -> f64 {
        let 差x = 点二.x - 点一.x;
        let 差y = 点二.y - 点一.y;
        (差x * 差x + 差y * 差y).sqrt()
    }
    
    fn main() {
        let 点一 = 点 { x: 0.0, y: 0.0 };
        let 点二 = 点 { x: 3.0, y: 4.0 };
        
        let 距离 = 计算距离(&点一, &点二);
        println!("点({}, {})和点({}, {})之间的距离是{}", 
                 点一.x, 点一.y, 点二.x, 点二.y, 距离);
    }
  2. 创建"矩形"结构体 :创建一个程序,定义矩形结构体并计算面积和周长:

    rust 复制代码
    struct 矩形 {
        长: f64,
        宽: f64,
    }
    
    fn 计算面积(矩形: &矩形) -> f64 {
        矩形.长 * 矩形.宽
    }
    
    fn 计算周长(矩形: &矩形) -> f64 {
        2.0 * (矩形.长 + 矩形.宽)
    }
    
    fn main() {
        let 我的矩形 = 矩形 { 长: 5.0, 宽: 3.0 };
        println!("矩形的长:{},宽:{}", 我的矩形.长, 我的矩形.宽);
        println!("面积:{}", 计算面积(&我的矩形));
        println!("周长:{}", 计算周长(&我的矩形));
    }

挑战练习(拓展)

  1. 创建"学生管理系统" :创建一个程序,使用向量存储学生结构体实例:

    rust 复制代码
    struct 学生 {
        姓名: String,
        年龄: i32,
        成绩: i32,
    }
    
    fn main() {
        let mut 学生们 = vec![
            学生 { 姓名: String::from("张三"), 年龄: 15, 成绩: 95 },
            学生 { 姓名: String::from("李四"), 年龄: 14, 成绩: 88 },
            学生 { 姓名: String::from("王五"), 年龄: 15, 成绩: 92 },
        ];
        
        // 添加新学生
        学生们.push(学生 { 姓名: String::from("赵六"), 年龄: 14, 成绩: 85 });
        
        // 打印所有学生信息
        println!("学生信息:");
        for (索引, 学生) in 学生们.iter().enumerate() {
            println!("第{}名:姓名:{},年龄:{}岁,成绩:{}分", 
                     索引 + 1, 学生.姓名, 学生.年龄, 学生.成绩);
        }
        
        // 计算平均成绩
        let mut 总分 = 0;
        for 学生 in &学生们 {
            总分 += 学生.成绩;
        }
        let 平均分 = 总分 as f64 / 学生们.len() as f64;
        println!("平均成绩:{}分", 平均分);
    }

4. 知识总结

核心概念回顾

  • 结构体:自定义的数据类型,包含多个字段
  • 字段:结构体中的数据成员,每个字段有自己的类型
  • 实例:根据结构体模板创建的具体对象
  • 访问字段:使用点号(.)访问结构体实例的字段
  • 修改字段 :需要使用mut关键字使结构体实例可变
  • 结构体更新语法:基于现有实例创建新实例,只修改部分字段

关键代码速查

功能 代码 说明
结构体定义 struct 结构体名 { 字段: 类型, ... } 定义一个结构体
创建实例 let 实例 = 结构体名 { 字段: 值, ... }; 创建结构体实例
访问字段 实例.字段 访问结构体字段
修改字段 实例.字段 = 值; 修改结构体字段(需要mut)
结构体更新 let 新实例 = 结构体名 { 字段: 新值, ..旧实例 }; 基于现有实例创建新实例

常见错误提醒

  1. 字段初始化:创建实例时必须为所有字段提供值
  2. 字段访问:不能访问不存在的字段
  3. 可变实例 :修改字段时需要使用mut关键字
  4. 所有权:结构体中的字段遵循Rust的所有权规则

5. 课后作业

巩固练习题

  1. 编写一个程序,定义"手机"结构体,包含品牌、型号、价格、颜色等字段
  2. 编写一个程序,定义"学校"结构体,包含名称、地址、学生人数等字段
  3. 编写一个程序,定义"电影"结构体,包含片名、导演、评分、上映年份等字段

创意编程题

  1. 发挥你的创意,创建一个程序,定义"游戏角色"结构体,包含姓名、等级、生命值、魔法值等字段
  2. 编写一个程序,定义"银行账户"结构体,包含账号、姓名、余额等字段,并实现存款、取款功能

下篇预习提示

下一篇我们将学习"成员功能------为结构体添加能力",就像学习如何为结构体添加方法,使它们具有更多的功能。预习一下:

  • 什么是方法?
  • 如何为结构体实现方法?
  • 方法与函数有什么区别?
  • 什么是关联函数?

恭喜你完成了第八篇教程!你已经掌握了结构体的定义和使用,学会了如何创建自定义数据类型。继续加油,下一篇我们将学习如何为结构体添加方法!

学习交流

如果你在学习过程中遇到任何问题,欢迎联系我:

  • ** 视频号,"时空系"
  • 邮箱: wbtm2718@qq.com
  • 其他提示:
  • 本人正在开发纯中文编程语言和编译器,有兴趣的可以交流
  • 本人正在写一本基于中国母语思维习惯的数学教材,可以让你一年内学完从初中到研究生的数学,而且可以让你快速掌握人工智能的关键数学知识,有兴趣的可以交流

祝你学习愉快!

相关推荐
yuweiade1 小时前
GO 快速升级Go版本
开发语言·redis·golang
lly2024061 小时前
SOAP Body 元素
开发语言
咸鱼2.03 小时前
【java入门到放弃】Dubbo
java·开发语言·dubbo
JAVA面经实录91710 小时前
Java企业级工程化·终极完整版背诵手册(无遗漏、全覆盖、面试+落地通用)
java·开发语言·面试
周杰伦fans11 小时前
AutoCAD .NET 二次开发:深入理解 EntityJig 的工作原理与正确实现
开发语言·.net
北方的流星11 小时前
华三路由器NAT配置
运维·网络·华三
数据法师11 小时前
开源情报收集工具GhostTrack深度测评:IP、手机号、用户名的合规信息查询方案
网络·网络协议·tcp/ip
Bat U12 小时前
JavaEE|多线程初阶(七)
java·开发语言
谭欣辰13 小时前
C++ 排列组合完整指南
开发语言·c++·算法