【Rust练习】14.流程控制
练习题来自:https://practice-zh.course.rs/flow-control.html
1
// 填空
fn main() {let n = 5;if n < 0 {println!("{} is negative", n);} __ n > 0 {println!("{} is positive", n);} __ {println!("{} is zero", n);}
}
非常简单的if-else
fn main() {let n = 5;if n < 0 {println!("{} is negative", n);} else if n > 0 {println!("{} is positive", n);} else {println!("{} is zero", n);}
}
2 🌟🌟 if/else 可以用作表达式来进行赋值
// 修复错误
fn main() {let n = 5;let big_n =if n < 10 && n > -10 {println!(" 数字太小,先增加 10 倍再说");10 * n} else {println!("数字太大,我们得让它减半");n / 2.0 ;}println!("{} -> {}", n, big_n);
}
能通过if
表达式直接赋值也是现代语言的一个新鲜玩意了,不知道为什么C++不打个补丁支持下。
fn main() {let n = 5;let big_n = if n < 10 && n > -10 {println!(" 数字太小,先增加 10 倍再说");10 * n} else {println!("数字太大,我们得让它减半");n / 2};println!("{} -> {}", n, big_n);
}
3 for in 可以用于迭代一个迭代器,例如序列 a…b.
fn main() {for n in 1..=100 { // 修改此行,让代码工作if n == 100 {panic!("NEVER LET THIS RUN")}}
}
始终记得Rust的range是一个左闭右开区间,想要包含右边就得加上等号就行,这里就要去掉。
fn main() {for n in 1..100 { // 修改此行,让代码工作if n == 100 {panic!("NEVER LET THIS RUN")}}
}
题外话:Rust 目前还是一个比较新的语言,主流的 IDE 为 VS Code(安装 rust-analyzer 插件)和 RustRover,前者无论商用还是非商用都是不收费的,后者非商用不收费,商用收费(应该是 Jetbrains 旗下第一个这么收费的,其他 IDE 都是任何使用都得收费)。下面提到的 VS Code 都指的是加载了 rust-analyzer 插件的。
就我个人的体验来看,两者各有各的长处。
这是 VS Code 的代码:
这是 Rustrover 的代码:
可以看到 VS Code 对变量的染色更充分一点,不过 Rustrover 对这个 range
的提示就很不错,你基本不可能认为会跑到 100。由于Rust存在类型推导的机制,因此当你不清楚变量的类型时,IDE提供的类型提示就尤为重要。这点 Rustrover 不如 VS Code,尤其是对于一些特征的推导,Rustrover 只能推导出基本类型,VS Code就能推导出impl trait
。
另外如果你想阅读库代码时,Rustrover有个将注释文档排版的功能,非常不错:
VS Code这边可能是考虑到你用浏览器也能访问本地排版好的文档,就没有这个功能,少开一个浏览器还是省了不少事的。
我们接下来的代码都以 VS Code 为基准 IDE。
4
// 修复错误,不要新增或删除代码行
fn main() {let names = [String::from("liming"),String::from("hanmeimei")];for name in names {// do something with name...}println!("{:?}", names);let numbers = [1, 2, 3];// numbers中的元素实现了 Copy,因此无需转移所有权for n in numbers {// do something with name...}println!("{:?}", numbers);
}
string
不是基本类型,因此需要借用
fn main() {let names = [String::from("liming"),String::from("hanmeimei")];for name in &names {// do something with name...}println!("{:?}", names);let numbers = [1, 2, 3];// numbers中的元素实现了 Copy,因此无需转移所有权for n in numbers {// do something with name...}println!("{:?}", numbers);
}
5
fn main() {let a = [4,3,2,1];// 通过索引和值的方式迭代数组 `a` for (i,v) in a.__ {println!("第{}个元素是{}",i+1,v);}
}
固定用法了。
fn main() {let a = [4,3,2,1];// 通过索引和值的方式迭代数组 `a` for (i,v) in a.iter().enumerate() {println!("第{}个元素是{}",i+1,v);}
}
6 🌟🌟 当条件为 true 时,while 将一直循环
// 填空,让最后一行的 println! 工作 !
fn main() {// 一个计数值let mut n = 1;// 当条件为真时,不停的循环while n __ 10 {if n % 15 == 0 {println!("fizzbuzz");} else if n % 3 == 0 {println!("fizz");} else if n % 5 == 0 {println!("buzz");} else {println!("{}", n);}__;}println!("n 的值是 {}, 循环结束",n);
}
这道题应该是拿大名鼎鼎的 Fizzbuzz
题目改的。
fn main() {// 一个计数值let mut n = 1;// 当条件为真时,不停的循环while n < 10 {if n % 15 == 0 {println!("fizzbuzz");} else if n % 3 == 0 {println!("fizz");} else if n % 5 == 0 {println!("buzz");} else {println!("{}", n);}n += 1;}println!("n 的值是 {}, 循环结束", n);
}
我就顺便把这道题做了吧,应该是我用Rust写的第一道算法题,之前用C++写过一遍。Fizzbuzz题目如下:
给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:
answer[i] == “FizzBuzz” 如果 i 同时是 3 和 5 的倍数。
answer[i] == “Fizz” 如果 i 是 3 的倍数。
answer[i] == “Buzz” 如果 i 是 5 的倍数。
answer[i] == i (以字符串形式)如果上述条件全不满足。
这里用 LeetCode 的提交格式:
impl Solution {pub fn fizz_buzz(n: i32) -> Vec<String> {let mut i = 1;let mut res: Vec<String> = Vec::new();while i <= n {if i % 15 == 0 {res.push("FizzBuzz".to_string());} else if i % 3 == 0 {res.push("Fizz".to_string());} else if i % 5 == 0 {res.push("Buzz".to_string());} else {res.push(i.to_string());}i += 1;}res}
}
7 🌟 使用 break 可以跳出循环
// 填空,不要修改其它代码
fn main() {let mut n = 0;for i in 0..=100 {if n == 66 {__}n += 1;}assert_eq!(n, 66);
}
答案
fn main() {let mut n = 0;for _ in 0..=100 {if n == 66 {break;}n += 1;}assert_eq!(n, 66);
}
8 🌟 continue 会结束当次循环并立即开始下一次循环
// 填空,不要修改其它代码
fn main() {let mut n = 0;for i in 0..=100 {if n != 66 {n+=1;__;}__}assert_eq!(n, 66);
}
答案
// 填空,不要修改其它代码
fn main() {let mut n = 0;for i in 0..=100 {if n != 66 {n+=1;continue;}break;}assert_eq!(n, 66);
}
9 🌟🌟 loop 一般都需要配合 break 或 continue 一起使用。
// 填空,不要修改其它代码
fn main() {let mut count = 0u32;println!("Let's count until infinity!");// 无限循环loop {count += 1;if count == 3 {println!("three");// 跳过当此循环的剩余代码__;}println!("{}", count);if count == 5 {println!("OK, that's enough");__;}}assert_eq!(count, 5);
}
答案
fn main() {let mut count = 0u32;println!("Let's count until infinity!");// 无限循环loop {count += 1;if count == 3 {println!("three");// 跳过当此循环的剩余代码continue;;}println!("{}", count);if count == 5 {println!("OK, that's enough");break;}}assert_eq!(count, 5);
}
C++是没有loop
(无限循环)的,很多其他的语言也没有,原因很明显,无限循环一旦不写终止条件,很容易就成了死循环。而Rust的编译器也没有智能到检测到死循环的存在,比如这里注释掉第二个if
的break
,loop
直接就死循环了,编译器也是很老实地跑,没有任何报错或者警告。倒是VS Code给了一个代码不可达(unreachable)的提示。
所以我不是很建议在代码里使用loop
。
10 🌟🌟 loop 是一个表达式,因此我们可以配合 break 来返回一个值
fn main() {let mut counter = 0;let result = loop {counter += 1;if counter == 10 {__;}};assert_eq!(result, 20);
}
很有意思的设计,C++实现类似功能估计要多写点代码——包个函数就有入栈出栈的性能损耗,直接修改又不容易让人意识到变量已经被修改了。
fn main() {let mut counter = 0;let result = loop {counter += 1;if counter == 10 {break counter;}};assert_eq!(result, 20);
}
11 🌟🌟🌟 当有多层循环时,你可以使用 continue 或 break 来控制外层的循环。要实现这一点,外部的循环必须拥有一个标签 'label, 然后在 break 或 continue 时指定该标签
// 填空
fn main() {let mut count = 0;'outer: loop {'inner1: loop {if count >= 20 {// 这只会跳出 inner1 循环break 'inner1; // 这里使用 `break` 也是一样的}count += 2;}count += 5;'inner2: loop {if count >= 30 {break 'outer;}continue 'outer;}}assert!(count == __)
}
答案
// 填空
fn main() {let mut count = 0;'outer: loop {'inner1: loop {if count >= 20 {// 这只会跳出 inner1 循环break 'inner1; // 这里使用 `break` 也是一样的}count += 2;}count += 5;'inner2: loop {if count >= 30 {break 'outer;}continue 'outer;}}assert!(count == 30)
}
对比其他语言的goto
,Rust的这个弱化了一点,仅仅能对循环打label
,但是这已经让人不好走查代码了。我的建议也是:不要用。几乎所有编程书在介绍语言里的goto
时都不建议使用,用起来很爽,看代码很痛苦。
相关文章:

【Rust练习】14.流程控制
练习题来自:https://practice-zh.course.rs/flow-control.html 1 // 填空 fn main() {let n 5;if n < 0 {println!("{} is negative", n);} __ n > 0 {println!("{} is positive", n);} __ {println!("{} is zero", n);} } …...
React-Hooks-Form 集成 Zod 校验库
React-Hooks-Form 集成 Zod 校验库 首先需要安装 react hooks form 官方提交的解析器 npm install hookform/resolvers再安装校验库 npm install zod它不仅支持 Zod 校验库同时还支持目前各种主流的校验库比如:Yup、Zod、Joi、Ajv、Vest、Custom 具体查看官方文…...

kettle从入门到精通 第八十五课 ETL之kettle kettle中javascript步骤调用外部javascript/js文件
场景:交流学习群里面有小伙伴咨询kettle中的javascript代码步骤如何调用外部js文件中的函数,觉得有点意思的,于是就抽时间整理了一下。 1、外部js文件为test.js,代码如下: function test(param){return "接收到了…...

比传统机器学习更先进的深度学习神经网络的二分类建模全流程教程
比传统机器学习更先进的深度学习神经网络的二分类建模全流程分析教程 深度学习介绍和与传统机器学习的区别 深度学习(Deep Learning)是一种机器学习的分支,基于多层神经网络模型,能够自动从大量数据中学习特征并进行预测。深度学…...
TeamTalk梳理概括
文章目录 即时通讯重点概括展开聊聊单聊消息流转流程展开聊聊群聊消息流转流程群成员管理数据库MySQL连接池设计redis连接池设计文件传输原理实时性并发能力 db_proxy_server reactor响应处理流程单聊消息消息如何封装?如何保证对端完整解析一帧消息?协议…...

构建“零工市场小程序”,服务灵活就业“大民生”
如今,灵活就业已成为现代劳动力市场的重要组成部分。然而,这一就业形态也面临着信息不对称、匹配效率低下等一系列挑战。为有效解决这些问题,构建一个高效、便捷的“零工市场小程序”显得尤为重要。 二、零工市场现状与挑战 市场规模与增长趋…...

【组件】前端js HEIC/HEIF 转换为JPEG、PNG或GIF格式 苹果格式
【组件】前端js HEIC/HEIF 转换为JPEG、PNG或GIF格式 Heic2any: Client-side conversion of HEIC/HEIF image files to JPEG,PNG, or GIF in the browser.https://alexcorvi.github.io/heic2any/#demo GitHub - alexcorvi/heic2any: Converting HEIF/HEIF image formats to PN…...
Vue3中slot插槽的几种使用实践
【1】默认插槽 父组件 <Category title"今日美食城市"><img :src"imgUrl" alt""> </Category>子组件 <div class"category"><h2>{{title}}</h2><slot>默认内容</slot> </div&g…...

SSH工具 MobaXterm的使用与快捷配置
软件下载/安装与链接服务器/本地虚拟机 文章目录 软件下载/安装与链接服务器/本地虚拟机软件下载软件安装使用软件链接非本地机器并设置用户密码我不想有确定密码的弹窗 其余便捷配置配置右键粘贴SSH链接设置 软件下载 如果你访问不了这个网址,可以评论区找博主或者…...
git 远程分支同步本地落后的有冲突的分支
如果你的本地分支已经修改了很多代码,但同时也已经落后于远程分支。这个时候你需要在主分支上拉最新的代码,然后切换到你的分支。 如主分支是 main ,从分支是xing。 首先切换到子分支 $ git checkout xing 然后请求merge主分支main的代码 …...

如何基于Java解析国密数字证书
一、说明 随着信息安全的重要性日益凸显,数字证书在各种安全通信场景中扮演着至关重要的角色。国密算法,作为我国自主研发的加密算法标准,其应用也愈发广泛。然而,在Java环境中解析使用国密算法的数字证书时,我们可能…...

java实现系统文件管理
java实现系统文件管理 环境:jdk17springbootVueElementUI 背景:公司所做的项目需要别的系统向我们服务器上传文件,当我们需要查看这些文件什么时候上传的、文件数据是怎样的,只能去机房,排查问题效率较低,…...
pytorch快速入门(一)—— 基本工具及平台介绍
前言 该pytorch学习笔记应该配合b站小土堆的《pytorch深度学习快速入门教程》使用 环境配置:Anaconda Python编译器:pycharm、jupyter 两大法宝函数 dir():知道包中有什么东西(函数 / 属性..…...

『功能项目』怪物的有限状态机【42】
本章项目成果展示 我们打开上一篇41项目优化 - 框架加载资源的项目, 本章要做的事情是按照框架的思想构建项目并完成怪物的自动巡逻状态,当主角靠近怪物时,怪物会朝向主角释放技能 首先新建脚本:BossCtrl.cs (通常把xxxCtrl.cs脚…...

【C++】模板进阶:深入解析模板特化
C语法相关知识点可以通过点击以下链接进行学习一起加油!命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与Queue 本章将…...

Python数据分析-世界上最富有的1000人
一、研究背景 随着全球化的加速发展和技术的进步,财富分配问题日益成为全球关注的焦点。财富的不平等现象日益明显,少数极富有的个人掌握了全球大部分的财富资源。了解全球最富有个人的财富分布及其背后的行业和国家因素,对于分析全球经济趋…...
CSS中隐藏滚动条的同时保留滚动功能
在CSS中,我们可以通过一些技巧来隐藏滚动条,同时保留滚动功能。以下是几种常用的方法和具体的实现步骤。 1. 使用 overflow 和 ::-webkit-scrollbar 这种方法适用于大多数现代浏览器。通过设置 overflow 属性启用滚动,同时利用 ::-webkit-s…...

我的标志:奇特的头像
<!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>与妖为邻</title><style>figu…...

中国空间计算产业链发展分析
2024中国空间计算产业链拆解 空间计算设备主要包括AR、VR、MR等终端设备。VR设备通常包括头戴式显示器(VR头盔)、手柄或追踪器等组件,用以完全封闭用户视野,营造虚拟环境体验。这些设备配备高分辨率显示屏、内置传感器和跟踪器。 …...

DAY14信息打点-JS 架构框架识别泄漏提取API 接口枚举FUZZ 爬虫插件项目
本课意义: 1.如何从表现中的JS提取价值信息 2.如何从地址中FUZZ提取未知的JS文件 3.如何从JS开放框架WebPack进行测试 一、JS 前端架构-识别&分析 在JS中寻找更多的URL地址,在JS代码逻辑(加密算法、APIKey配置、验证逻辑)中进…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...