【Rust练习】12.枚举

练习题来自:https://practice-zh.course.rs/compound-types/enum.html

1


// 修复错误
enum Number {Zero,One,Two,
}enum Number1 {Zero = 0,One,Two,
}// C语言风格的枚举定义
enum Number2 {Zero = 0.0,One = 1.0,Two = 2.0,
}fn main() {// 通过 `as` 可以将枚举值强转为整数类型assert_eq!(Number::One, Number1::One);assert_eq!(Number1::One, Number2::One);
} 

枚举的值不能是f64浮点数,另外,两个枚举值不能直接进行比较,因为没有实现Debug的特征。可以手动实现Debug,这里我们还是按作者的想法改。

// C语言风格的枚举定义
enum Number2 {Zero = 0,One = 1,Two = 2,
}fn main() {// 通过 `as` 可以将枚举值强转为整数类型assert_eq!(Number::One as u64, Number1::One as u64);assert_eq!(Number1::One as u64, Number2::One as u64);
} 

Rust的枚举和C++完全不一样,C++11中的enum class已经禁止了枚举值直接和数值的比较,但是枚举的范围还是仅限常量,Rust则非常灵活,可以包含各种数据。不过事实上,这是Rust实现“多态”的一种思路,对于C++来说,继承就够了。

某些场景下(比如你确信你的枚举不会引发额外的问题),使用C语言传统的枚举会提升开发效率,但是Rust并不相信自己的程序员有这个能力。

2 枚举成员可以持有各种类型的值

// 填空
enum Message {Quit,Move { x: i32, y: i32 },Write(String),ChangeColor(i32, i32, i32),
}fn main() {let msg1 = Message::Move{__}; // 使用x = 1, y = 2 来初始化let msg2 = Message::Write(__); // 使用 "hello, world!" 来初始化
} 

答案

fn main() {let msg1 = Message::Move{y:2, x:1}; // 使用x = 1, y = 2 来初始化let msg2 = Message::Write(String::from("hello, world!")); // 使用 "hello, world!" 来初始化
} 

这就是我刚才说的,可以包含各种数据。

3


// 仅填空并修复错误
enum Message {Quit,Move { x: i32, y: i32 },Write(String),ChangeColor(i32, i32, i32),
}fn main() {let msg = Message::Move{x: 1, y: 2};if let Message::Move{__} = msg {assert_eq!(a, b);} else {panic!("不要让这行代码运行!");}
} 

作者有的题目出得就突出一个迷惑,这题就是,不走到panicassert也过不了,这种题目的意义是什么?

fn main() {let msg = Message::Move{x: 1, y: 2};if let Message::Move{x:a,y: b} = msg {assert_eq!(a, b);} else {panic!("不要让这行代码运行!");}
} 

4 🌟🌟 使用枚举对类型进行同一化


// 填空,并修复错误
enum Message {Quit,Move { x: i32, y: i32 },Write(String),ChangeColor(i32, i32, i32),
}fn main() {let msgs: __ = [Message::Quit,Message::Move{x:1, y:3},Message::ChangeColor(255,255,0)];for msg in msgs {show_message(msg)}
} fn show_message(msg: Message) {println!("{}", msg);
}

这是一个数组,按数组的语法即可:

#[derive(Debug)]
// 填空,并修复错误
enum Message {Quit,Move { x: i32, y: i32 },Write(String),ChangeColor(i32, i32, i32),
}fn main() {let msgs: [Message; 3] = [Message::Quit,Message::Move{x:1, y:3},Message::ChangeColor(255,255,0)];for msg in msgs {show_message(msg)}
} fn show_message(msg: Message) {println!("{:?}", msg);
}

5 🌟🌟 Rust 中没有 null,我们通过 Option 枚举来处理值为空的情况

// 填空让 `println` 输出,同时添加一些代码不要让最后一行的 `panic` 执行到
fn main() {let five = Some(5);let six = plus_one(five);let none = plus_one(None);if let __ = six {println!("{}", n)} panic!("不要让这行代码运行!");
} fn plus_one(x: Option<i32>) -> Option<i32> {match x {__ => None,__ => Some(i + 1),}
}

注意Rust中的if使用的是单等于号,这种match的语法,写过Kotlin的我其实还能接受,都是为了简化代码。

fn main() {let five = Some(5);let six = plus_one(five);let none = plus_one(None);if let Some(n) = six {println!("{}", n)} return;panic!("不要让这行代码运行!");
} fn plus_one(x: Option<i32>) -> Option<i32> {match x {None => None,Some(i) => Some(i + 1),}
}

至于这个Option,C++有个类似的std::optional,我写过文章介绍:【C++】optional的使用(一),这就是后发优势,optional是C++17才引入的,此前已经有了继承自C语言的null和C++自己的nullptr,想全改成optional就不能保证兼容性。

6 🌟🌟🌟🌟 使用枚举来实现链表.


// 填空,让代码运行
use crate::List::*;enum List {// Cons: 链表中包含有值的节点,节点是元组类型,第一个元素是节点的值,第二个元素是指向下一个节点的指针Cons(u32, Box<List>),// Nil: 链表中的最后一个节点,用于说明链表的结束Nil,
}// 为枚举实现一些方法
impl List {// 创建空的链表fn new() -> List {// 因为没有节点,所以直接返回 Nil 节点// 枚举成员 Nil 的类型是 ListNil}// 在老的链表前面新增一个节点,并返回新的链表fn prepend(self, elem: u32) -> __ {Cons(elem, Box::new(self))}// 返回链表的长度fn len(&self) -> u32 {match *self {// 这里我们不能拿走 tail 的所有权,因此需要获取它的引用Cons(_, __ tail) => 1 + tail.len(),// 空链表的长度为 0Nil => 0}}// 返回链表的字符串表现形式,用于打印输出fn stringify(&self) -> String {match *self {Cons(head, ref tail) => {// 递归生成字符串format!("{}, {}", head, tail.__())},Nil => {format!("Nil")},}}
}fn main() {// 创建一个新的链表(也是空的)let mut list = List::new();// 添加一些元素list = list.prepend(1);list = list.prepend(2);list = list.prepend(3);// 打印列表的当前状态println!("链表的长度是: {}", list.len());println!("{}", list.stringify());
}

答案如下:


// 填空,让代码运行
use crate::List::*;enum List {// Cons: 链表中包含有值的节点,节点是元组类型,第一个元素是节点的值,第二个元素是指向下一个节点的指针Cons(u32, Box<List>),// Nil: 链表中的最后一个节点,用于说明链表的结束Nil,
}// 为枚举实现一些方法
impl List {// 创建空的链表fn new() -> List {// 因为没有节点,所以直接返回 Nil 节点// 枚举成员 Nil 的类型是 ListNil}// 在老的链表前面新增一个节点,并返回新的链表fn prepend(self, elem: u32) -> List {Cons(elem, Box::new(self))}// 返回链表的长度fn len(&self) -> u32 {match *self {// 这里我们不能拿走 tail 的所有权,因此需要获取它的引用Cons(__, ref tail) => 1 + tail.len(),// 空链表的长度为 0Nil => 0}}// 返回链表的字符串表现形式,用于打印输出fn stringify(&self) -> String {match *self {Cons(head, ref tail) => {// 递归生成字符串format!("{}, {}", head, tail.stringify())},Nil => {format!("Nil")},}}
}fn main() {// 创建一个新的链表(也是空的)let mut list = List::new();// 添加一些元素list = list.prepend(1);list = list.prepend(2);list = list.prepend(3);// 打印列表的当前状态println!("链表的长度是: {}", list.len());println!("{}", list.stringify());
}

Rust官方曾经提到,现代编程语言不是很需要链表。事实上Rust因为所有权的原因,实现一个链表是要比其他语言困难的。

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

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

相关文章

使用FFmpeg的AVFilter转换YUV到RGB

AVFilter 是 FFmpeg 库 libavfilter 的核心组件&#xff0c;提供了一套强大的音视频处理框架&#xff0c;用于对音视频流进行复杂的过滤、转换和效果处理。通过 AVFilter&#xff0c;开发者可以构建自定义的滤镜图&#xff08;filter graph&#xff09;&#xff0c;实现各种音视…

(每日一问)操作系统:常见的 Linux 指令详解

&#xff08;每日一问&#xff09;操作系统&#xff1a;常见的 Linux 指令详解 Linux 系统作为一种开源的操作系统&#xff0c;以其高效、稳定和安全的特性&#xff0c;广泛应用于服务器、开发环境和嵌入式系统等领域。日常使用 Linux&#xff0c;掌握常见的基本指令至关重要&a…

Transformer预测 | 基于Transformer心率时间序列预测(tensorflow)

效果一览 基本介绍 Transformer预测 | 基于Transformer心率时间序列预测(tensorflow) 程序设计 import pandas as pd from pandas.plotting import lag_plot from statsmodels.graphics

EP1 banner海报swiper轮播器

文件路径&#xff1a; E:/homework/uniappv3tswallpaper/pages/index/index.vue <template><view class"homeLayout"><view class"banner"><swiper :indicator-dots"true" :autoplay"true" :interval"3000…

变量数据类型 Day3

1. 变量 1.1 变量的概念 变量是计算机内存中的一块存储单元&#xff0c;是存储数据的基本单元变量的组成包括&#xff1a;数据类型、变量名、值&#xff0c;后文会具体描述变量的本质作用就是去记录数据的&#xff0c;比如说记录一个人的身高、体重、年龄&#xff0c;就需要去…

script中的src

<script src"http://www.somewhere.com/afile.js"></script> 浏览器在解析这个资源时&#xff0c;会向 src 属性指定的路径发送一个 GET 请求&#xff0c;以取得相应资源&#xff0c;假定 是一个 JavaScript 文件。这个初始的请求不受浏览器同源策略限…

Verilog基础,原码,反码与补码的概念

Verilog模块初认识 1、Verilog模块(Module) Verilog中的module可以看成一个具有输入输出端口的黑盒子&#xff0c;该黑盒子有输入和输出接口(信号)&#xff0c;通过把输入在盒子中执行某些操作来实现某项功能。(类似于C语言中的函数) 图1 模块示意图 1.1 模块描述 图1 所示的…

2024年【防爆电气】试题及解析及防爆电气模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 防爆电气试题及解析考前必练&#xff01;安全生产模拟考试一点通每个月更新防爆电气模拟考试题库题目及答案&#xff01;多做几遍&#xff0c;其实通过防爆电气复审模拟考试很简单。 1、【单选题】()利用输送爆炸危险…

Einsum(Einstein summation convention)

Einsum&#xff08;Einstein summation convention&#xff09; 笔记来源&#xff1a; Permute和Reshape嫌麻烦&#xff1f;einsum来帮忙&#xff01; The Einstein summation convention is a notational shorthand used in tensor calculus, particularly in the fields of …

大美祖国之地名篇-探寻全国同名地名

目录 前言 一、地名数据库 1、数据库模型 2、数据表结构 二、实践之旅&#xff0c;发现同名地名 1、省、市同名 2、市、县同名 3、 区县、乡镇同名 4、乡镇和村委会同名 三、总结 前言 我们祖国地大物博&#xff0c;从北到南&#xff0c;从东到西。祖国位于亚洲东部&…

九,自定义转换器详细操作(附+详细源码解析)

九&#xff0c;自定义转换器详细操作&#xff08;附详细源码解析&#xff09; 文章目录 九&#xff0c;自定义转换器详细操作&#xff08;附详细源码解析&#xff09;1. 基本介绍2. 准备工作3. 自定义转换器操作4. 自定义转换器的注意事项和细节5. 总结&#xff1a;6. 最后&…

电脑怎么限制软件上网?推荐三个超详细的小妙招(软件上网权限管理)

想要控制电脑上哪些软件可以上网、哪些不能&#xff1f;不管是为了保护隐私、节省流量&#xff0c;还是提高工作效率&#xff0c;限制软件上网都是非常实用的小妙招&#xff01; 今天给大家带来三个超详细的招数&#xff0c;帮助你轻松管理软件的上网权限。让那些不该上网的应…

最长的指定瑕疵度的元音子串

题 目描述 开头和结尾都是元音字母(aeiouAEIOU)的字符串为元音字符串&#xff0c;其中混杂的非元音字母数量为其瑕疵度。比如. 1.“a”、“aa"是元音字符串&#xff0c;其瑕疵度都为02.“aiur"不是元音字符串(结尾不是元音字符)3.“abira”是元音字符串&#xff0c…

RocketMQ 集群与高可用性:深入解析与实践指南

目录 前言 RocketMQ集群与高可用性 一、主从同步机制 1.1 使用场景 1.2 原理机制 1.3 数据同步流程 1.4 优缺点 二、RocketMQ 故障转移机制&#xff08;Failover&#xff09; 2.1 使用场景 2.2 原理机制 2.3 故障转移的注意事项 2.4 优缺点 三、主从架构和故障转移…

MySQL的 where 1=1会不会影响性能

MySQL的 where 11会不会影响性能&#xff1f; 一、引言 在编写SQL语句时&#xff0c;我们经常会遇到需要动态拼接查询条件的情况&#xff0c;尤其是在使用MyBatis这类ORM框架时。为了简化代码&#xff0c;很多开发者会使用where 11来开始他们的查询语句&#xff0c;然后通过程…

VSCode学习笔记

1. 快捷键 KeyDescriptionPlatformF1打开命令面板&#xff08;Command Palette&#xff09;Win10Shift Delete剪切当前光标所在的代码行Win10 2. 文件 2.1 在文件列表中定位当前文件 操作路径&#xff1a;右键单击文件名 ⇒ 在右键菜单中点击 【Reveal in Explorer View】

云计算第四阶段----CLOUD 01-03

CLOUD Day01 一、虚拟化平台搭建 虚拟化技术产品介绍 #黄线标注的&#xff0c;都是比较主流且常用的虚拟化平台。 虚拟化与云计算的关系 虚拟化是一种技术&#xff0c;它允许在单个物理服务器上创建和运行多个虚拟机&#xff08;VMs&#xff09;&#xff0c;每个虚拟机都有其…

python编程知识(实现数据加密和解密)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

JavaScript使用高德API显示地图

前言 在JavaScript中&#xff0c;使用Leaflet库显示地图是一种常见的做法。Leaflet是一个开源的JavaScript库&#xff0c;用于在Web应用程序中创建互动地图。它非常轻量级&#xff0c;易于使用&#xff0c;并且提供了多种功能&#xff0c;使开发者能够轻松地将地图集成到他们的…

银行结算业务

1.1 银行本票 银行本票是由银行签发的,承诺自己在见票时无条件支付票款给收款人或持票人的业务。银行本票按票面划分为定额本票和不定额本票,按币种划分为人民币银行本票和外币银行本票。人民币银行本票仅在同一交换区域内使用,资金清算利用当地人民银行组织的资金清算形式…