【Rust】枚举和模式匹配——Rust语言基础14

文章目录

  • 1. 枚举类型
    • 1.2. Option 枚举
  • 2. match 控制流结构
    • 2.1. match 对绑定值的匹配
    • 2.2. Option<T> 的匹配
    • 2.3. 通配模式以及 _ 占位符
  • 3. if let 控制流
  • 4. 小测试

1. 枚举类型

枚举(enumerations),也被称作 enums。枚举允许你通过列举可能的成员(variants)来定义一个类型。首先,我们会定义并使用一个枚举来展示它是如何连同数据一起编码信息的。枚举类型可以看作是一个类型的集合。

例如下面这样定义一个枚举:

enum Lunch {duck,rabbit,chicken,
};

对没错,上面的例子展示了一个经典的鸡兔同笼的场景。

问题:笼子里有3只鸡,6只鸭子,5只兔子,请问为什么有37只脚?
答:因为有一只鸡在独立。

问题:笼子里有3只鸡,6只鸭子,5只兔子,请问为什么有36只脚?
答:因为有两只鸡在独立!
回答错误!!
正确回答:因为有一只鸡在睡觉没看到脚。

好了,开个玩笑,定义一个枚举变量就像上面一样简单。

如下便是使用枚举变量的示例:

	let goku = Lunck::chichen;let kuririn = Lunck::duck;

相信有其他编程语言基础的同学对此一定不会陌生,不过更有趣的是,在 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"));

亦或者是这样。

enum Message {Quit,Move { x: i32, y: i32 },Write(String),ChangeColor(i32, i32, i32),
}

这些类型的指定都是被 rust 所允许的。请告诉我你们没有忘记这些类型代表什么意义吧~,好吧忘了也没关系,再来复习一次:

  • Quit 没有关联任何数据。
  • Move 类似结构体包含命名字段。
  • Write 包含单独一个 String
  • ChangeColor 包含三个 i32

上面的枚举类型等同于多个结构体类型的定义:

struct QuitMessage; // 类单元结构体
struct MoveMessage {x: i32,y: i32,
}
struct WriteMessage(String); // 元组结构体
struct ChangeColorMessage(i32, i32, i32); // 元组结构体

这样看枚举在一定程度上是会比结构体要方便多了,而且枚举变量同样可以通过 impl 块来定义属于该枚举的方法:

    impl Message {fn call(&self) {// 在这里定义方法体}}let m = Message::Write(String::from("hello"));m.call();

1.2. Option 枚举

Option 也是一个枚举类型,在 rust 中没有空值 Null 的概念,由于考虑到所有变量都存在一种空值和非空值的状态会为编程语言带了巨大问题甚至是会引起各种漏洞,因此 rust 摒弃了这一设计理念,但由于空值同时也具有特殊意义,又会为编程带来很多便利,取而代之则衍生出 Option 这样的枚举。

rust 标准库中是这样定义的:

enum Option<T> {None,Some(T),
}

这里的 <T> 语法是一个泛型参数,虽然目前还没学习到,但相信大家也不陌生,泛型在其它编程语言中也是很常见和重要的存在。这里的 None 就表示没有值,一定程度上等价于 Null 的作用。

2. match 控制流结构

Rust 有一个叫做 match 的极为强大的控制流运算符,它允许我们将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码。模式可由字面值、变量、通配符和许多其他内容构成;。match 的力量来源于模式的表现力以及编译器检查,它确保了所有可能的情况都得到处理。

假设有这样一个场景,现在要上海陆家嘴举办 2025 年天下第一武道大会,邀请了:

  • 埼玉《一拳超人》
  • 五条悟《咒术回战》
  • 孙悟空《七龙珠》
  • 漩涡鸣人《火影忍者》
  • 贝吉塔《七龙珠》
  • 蒙奇·D·路飞《海贼王》

这些著名高手来参加,现在要根据这些选手的战斗能力为他们做排名。

enum Hero {Saitama,Satoru,Goku,Naruto,Bejita,Ruffy,
}fn rank(hero: Hero) -> u8 {match hero {Hero:Saitama => 1,Hero:Satoru=> 2,Hero:Goku=> 3,Hero:Naruto=> 4,Hero:Bejita=> 5,Hero:Ruffy=> 6,}
}

[注]:这里主持人给的排名仅作为参考,并不具备实际意义,请根据大家自己内心估值来判断。也不要问为什么没有请某某某来,上海市举办方表示资金有限,请不起所有高手聚集此地。

好了,根据上面的简单例子相信各位也能够对 match 的功能了解一二,这里就有人站出来说了“这?这不就是 switch & case 语句嘛~”,欸,差不多,但是 rustmatch 要更加强大一点,请继续往下看。

2.1. match 对绑定值的匹配

正如上文提到,枚举变量可以为其成员指定几乎任何类型,对这种情况 match 该如何应对?

enum Hero {Saitama(i32),Satoru(i32),Goku(i32),Naruto(i32),Bejita(i32),Ruffy(i32),
}
// 整数表示其战斗力数值fn power(hero: Hero) {match hero {Hero::Saitama(p) => {println!("埼玉: {}", p);},Hero::Satoru(p) => {println!("五条: {}", p);},Hero::Goku(p) => {println!("悟空: {}", p);},Hero::Naruto(p) => {println!("鸣人: {}", p);},Hero::Bejita(p) => {println!("王子: {}", p);},Hero::Ruffy(p) => {println!("草帽小子: {}", p);},}
}fn main() {let goku = Hero::Goku(12000);power(&goku);
}

rust 中允许这样的匹配,正如上述例子中,将会匹配到 goku 属于 Hero::Goku(p) 类型,并同时将其值绑定到了 p 变量,这样就可以获取其战斗力数值了。

2.2. Option 的匹配

比如我们想要编写一个函数,它获取一个 Option<i32> ,如果其中含有一个值,将其加一。如果其中没有值,函数应该返回 None 值,而不尝试执行任何操作。

得益于 match,编写这个函数非常简单:

    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);

让我们更仔细地检查 plus_one 的第一行操作。当调用 plus_one(five) 时,plus_one 函数体中的 x 将会是值 Some(5)。接着将其与每个分支比较。

            None => None,

Some(5) 并不匹配模式 None,所以继续进行下一个分支。

            Some(i) => Some(i + 1),

Some(5)Some(i) 匹配吗?当然匹配!它们是相同的成员。i 绑定了 Some 中包含的值,所以 i 的值是 5。接着匹配分支的代码被执行,所以我们将 i 的值加一并返回一个含有值 6 的新 Some

需要注意的一点是,match 匹配是穷举匹配,必须要为所有可能的结果编写对应的匹配处理过程,否则编译器将会阻止这种情况。

2.3. 通配模式以及 _ 占位符

将上面的代码做以简单改动:

enum Hero {Saitama(i32),Satoru(i32),Goku(i32),Naruto(i32),Bejita(i32),Ruffy(i32),
}
// 整数表示其战斗力数值fn power(hero: Hero) {match hero {Hero::Saitama(p) => {println!("埼玉: {}", p);},Hero::Satoru(p) => {println!("五条: {}", p);},other => {// _ => {	// 与上一行代码等价println!("战斗能力未知!!!");},}
}fn main() {let goku = Hero::Goku(12000);power(&goku);
}

最后一个分支则涵盖了所有其他可能的值,模式是我们命名为 other 的一个变量。

3. if let 控制流

这个语法很像 C/C++ 中的 if 语句,因此掌握起来也非常容易,还是照例给个例子看的比较直白一些:

enum Hero {Saitama(i32),Satoru(i32),Goku(i32),Naruto(i32),Bejita(i32),Ruffy(i32),
}fn main() {let goku = Hero::Goku(12000);//power(&goku);//if let Hero::Goku(p) = goku {println!("悟空: {}", p);} else {println!("战斗能力未知!!!");}}

相信这样简单的例子大家一看便能够明了,当 if let 的条件成立将会进入下方代码块,否则不会,就是这样简单的语句。

4. 小测试

这样以来,条件控制语句我们也掌握的差不多了,看完了,也懂了,让我们试着用一下吧。

接下来我们要实现一个这样的场景,接着上面天下第一武道大会结束之后,还是这些参赛选手们听闻孙悟空会一个绝技“融合”!每个人都很感兴趣,都希望试试自己与另外一个人融合之后会产生什么样的现象。

假设融合对象只能是如下:

  • 五条悟 & 漩涡鸣人
  • 埼玉 & 路飞
  • 孙悟空 & 贝吉塔
  • 其它情况则融合失败。
impl Hero {fn fusion(&self, other: &Hero) -> Hero {match self {Hero::Saitama(p) | Hero::Ruffy(p) => {Hero::Saiffy(self.get() + other.get(), String::from("saitama&ruffy"))},Hero::Satoru(p) | Hero::Naruto(p) => {Hero::Natoru(self.get() + other.get(), String::from("satoru&naruto"))},Hero::Goku(p) | Hero::Bejita(p) => {Hero::Gojita(self.get() + other.get(), String::from("goku&bejita"))},other => {println!("融合失败!!!");Hero::NULL},}}fn get(&self) -> &i32 {match self {Hero::Saitama(p) => p,Hero::Satoru(p) => p,Hero::Goku(p) => p,Hero::Naruto(p) => p,Hero::Bejita(p) => p,Hero::Ruffy(p) => p,other => &0,}}
}#[derive(Debug)]
enum Hero {Saitama(i32),Satoru(i32),Goku(i32),Naruto(i32),Bejita(i32),Ruffy(i32),NULL,Gojita(i32, String),Natoru(i32, String),Saiffy(i32, String),
}fn main() {let goku = Hero::Goku(12000);let bejita = Hero::Bejita(16000);let gojita = Hero::fusion(&goku, &bejita);println!("goku+bejita = {:?}", gojita);
}

[注]:上面代码仅供读者参考,希望大家能够实现出更加有趣的代码~

下一篇《Rust语言基础15》


觉得这篇文章对你有帮助的话,就留下一个赞吧v*
请尊重作者,转载还请注明出处!感谢配合~
[作者]: Imagine Miracle
[版权]: 本作品采用知识共享署名-非商业性-相同方式共享 4.0 国际许可协议进行许可。
[本文链接]: https://blog.csdn.net/qq_36393978/article/details/146249359

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/72298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【商城实战(25)】解锁UniApp移动端适配秘籍,打造完美商城体验

【商城实战】专栏重磅来袭&#xff01;这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建&#xff0c;运用 uniapp、Element Plus、SpringBoot 搭建商城框架&#xff0c;到用户、商品、订单等核心模块开发&#xff0c;再到性能优化、安全加固、多端适配&#xf…

《C++ Primer》学习笔记(二)

第二部分&#xff1a;C标准库 1.为了支持不同种类的IO处理操作&#xff0c;标准库定义了以下类型的IO&#xff0c;分别定义在三个独立的文件中&#xff1a;iostream文件中定义了用于读写流的基本类型&#xff1b;fstream文件中定义了读写命名文件的类型&#xff1b;sstream文件…

MATLAB风光柴储微网粒子群算法

本程序实现了风光柴储微网中的粒子群优化&#xff08;PSO&#xff09;算法&#xff0c;用于优化微网的能源调度问题。具体来说&#xff0c;程序考虑了光伏发电、风力发电、柴油机发电&#xff08;柴储&#xff09;&#xff0c;并使用粒子群算法来优化这些能源的调度&#xff0c…

解决Windows版Redis无法远程连接的问题

&#x1f31f; 解决Windows版Redis无法远程连接的问题 在Windows系统下使用Redis时&#xff0c;很多用户会遇到无法远程连接的问题。尤其是在配置了Redis并尝试通过工具如RedisDesktopManager连接时&#xff0c;可能会报错“Cannot connect to ‘redisconnection’”。今天&am…

解决 HTTP 请求中的编码问题:从乱码到正确传输

文章目录 解决 HTTP 请求中的编码问题&#xff1a;从乱码到正确传输1. **问题背景**2. **乱码问题的原因**2.1 **客户端编码问题**2.2 **请求头缺失**2.3 **服务器编码问题** 3. **解决方案**3.1 **明确指定请求体编码**3.2 **确保请求头正确**3.3 **动态获取响应编码** 4. **调…

VS Code 配置优化指南

目录 一、安装与基础设置1. 安装 VS Code2. 中文语言包 二、插件推荐三、常见配置项与优化1. 用户 / 工作区设置2. 全局配置 / Settings Sync3. 常用设置示例 四、性能优化五、调试与终端配置1. 调试配置2. 内置终端配置 六、快捷键配置七、美观与主题八、总结 VS Code&#xf…

基于NXP+FPGA永磁同步电机牵引控制单元(单板结构/机箱结构)

永磁同步电机牵引控制单元&#xff08;单板结构/机箱结构&#xff09; 永磁同步电机牵引控制单元&#xff08;TCU-PMSM&#xff09;用于牵引逆变器-永磁同步电机构成的牵引电传动系统&#xff0c;采用轴控方式。执行高性能永磁同步电机复矢量控制策略&#xff0c;具有响应迅速…

/etc/sysconfig/jenkins 没有这个文件

在 CentOS 或其他基于 Red Hat 的 Linux 系统中&#xff0c;/etc/sysconfig/jenkins 文件通常用来存储 Jenkins 的配置参数&#xff0c;例如 JENKINS_HOME 的路径。但是&#xff0c;如果你发现没有这个文件&#xff0c;你可以通过以下几种方式来解决或确认&#xff1a; 检查 J…

conda 安装软件报错 Found conflicts! Looking for incompatible packages.

问题描述&#xff1a; 利用 conda 安装某包 conda install -c "nvidia/label/cuda-11.8.0" cuda-nvcc时发现报错&#xff1a; Collecting package metadata (current_repodata.json): done Solving environment: failed with initial frozen solve. Retrying with…

MySQL 衍生表(Derived Tables)

在SQL的查询语句select …. from …中&#xff0c;跟在from子句后面的通常是一张拥有定义的实体表&#xff0c;而有的时候我们会用子查询来扮演实体表的角色&#xff0c;这个在from子句中的子查询会返回一个结果集&#xff0c;这个结果集可以像普通的实体表一样查询、连接&…

STM32配套程序接线图

1 工程模板 2 LED闪烁 3LED流水灯 4蜂鸣器 5按键控制LED 6光敏传感器控制蜂鸣器 7OLED显示屏 8对射式红外传感器计次 9旋转编码器计次 10 定时器定时中断 11定时器外部时钟 12PWM驱动LED呼吸灯 13 PWM驱动舵机 14 PWM驱动直流电机 15输入捕获模式测频率 16PWMI模式测频率占空…

鸿蒙初级考试备忘

Module类型 Module按照使用场景可以分为两种类型&#xff1a; Ability类型的Module&#xff1a; 用于实现应用的功能和特性。每一个Ability类型的Module编译后&#xff0c;会生成一个以.hap为后缀的文件&#xff0c;我们称其为HAP&#xff08;Harmony Ability Package&#x…

语音识别踩坑记录

本来想在原来的语音识别的基础上增加本地扩展本地词典&#xff0c; 采用的语音识别是Vosk识别器&#xff0c;模型是 vosk-model-small-cn-0.22 // 初始化Vosk识别器 if (recognizer null) {using (Model model new Model(modelPath)){string grammar "{""…

SpringCloud 学习笔记1(Spring概述、工程搭建、注册中心、负载均衡、 SpringCloud LoadBalancer)

文章目录 SpringCloudSpringCloud 概述集群和分布式集群和分布式的区别和联系 微服务什么是微服务&#xff1f;分布式架构和微服务架构的区别微服务的优缺点&#xff1f;拆分微服务原则 什么是 SpringCloud &#xff1f;核心功能与组件 工程搭建父项目的 pom 文件 注册中心Rest…

计算机网络-网络规划与设计

基本流程 需求分析—》通信规范分析—》逻辑网络设计—》物理网络设计—》实施阶段 需求分析&#xff1a; 确定需求&#xff0c;包括&#xff1a;业务需求、用户需求、应用需求、计算机平台需求、网络通信需求等。 产物&#xff1a;需求规范 通信规范分析&#xff1a; 现有…

《AI浪潮中的璀璨新星:Meta Llama、Ollama与DeepSeek的深度剖析》:此文为AI自动生成

《AI浪潮中的璀璨新星&#xff1a;Meta Llama、Ollama与DeepSeek的深度剖析》&#xff1a;此文为AI自动生成 引言&#xff1a;AI 大模型的群雄逐鹿时代 在科技飞速发展的当下&#xff0c;AI 大模型领域已成为全球瞩目的焦点&#xff0c;竞争激烈程度堪称白热化。从 OpenAI 推出…

基础知识《HTTP字段与状态码详细说明》

HTTP 协议字段与状态码完整指南 一、HTTP 字段&#xff08;请求头与响应头&#xff09; HTTP 头字段用于传递客户端和服务器之间的元数据&#xff0c;分为 请求头&#xff08;Request Headers&#xff09; 和 响应头&#xff08;Response Headers&#xff09;。 1. 常见请求头…

DeepSeek linux服务器(CentOS)部署命令笔记

Linux&#xff08;CentOS&#xff09;FinalShellOllama远程访问&#xff0c;本地部署deepseek 自备CentOS服务器&#xff0c;并且已经使用FinalShell连接到服务器 一、准备工作 1.更新服务器 apt-get update-y 2.下载Ollama curl -fsSL https://ollama.com/install.sh | …

C#通过API接口返回流式响应内容---分块编码方式

1、背景 上一篇文章《C#通过API接口返回流式响应内容—SSE方式》阐述了通过SSE&#xff08;Server Send Event&#xff09;方式&#xff0c;由服务器端推送数据到浏览器。本篇是通过分块编码的方式实现 2、效果 3、具体代码 3.1 API端实现 [HttpGet] public async Task Chu…

SSL 原理及实验

引言 为了实现远程办公或者远程客户访问内网的资源 &#xff08;1&#xff09;回顾历史&#xff1a; 起初先出现SSL(Secure Sockets Layer&#xff09;&#xff0d;安全套接层协议。 美国网景Netscape公司1994年研发&#xff0c;介于传输层TCP协议和应用层协议之间的一种协议…