当前位置: 首页 > news >正文

【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 的代码:
rust-analyzer 0.3.2104
这是 Rustrover 的代码:
RustRover 2024.1.3
可以看到 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的编译器也没有智能到检测到死循环的存在,比如这里注释掉第二个ifbreakloop直接就死循环了,编译器也是很老实地跑,没有任何报错或者警告。倒是VS Code给了一个代码不可达(unreachable)的提示。
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时都不建议使用,用起来很爽,看代码很痛苦。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 详细分析linux中的MySql跳过密码验证以及Bug(图文)
  • Vue3+TypeScript+Vite+Less 开发 H5 项目(amfe-flexible + postcss-pxtorem)
  • MySQL数据的增删改查(二)
  • git update-ref
  • Axure科技感大屏系统设计:智慧农场管理平台
  • TDengine 签约寓信科技,推动智慧公寓的数字化转型
  • 升级VMware
  • 【计算机网络 - 基础问题】每日 3 题(一)
  • 【大模型专栏—实战篇】基于RAG从0到1搭建AI科研知识库
  • 原型模式:克隆对象的艺术
  • 如何训练机器学习力场
  • 绑定变量对于SQL性能的影响
  • 九、外观模式
  • android BLE 蓝牙的连接(二)
  • turbo译码算法MAX, MAX_SCALE and MAX_STAR的比较
  • [译]前端离线指南(上)
  • Angular 2 DI - IoC DI - 1
  • Cumulo 的 ClojureScript 模块已经成型
  • egg(89)--egg之redis的发布和订阅
  • git 常用命令
  • Java IO学习笔记一
  • mongo索引构建
  • rc-form之最单纯情况
  • React-redux的原理以及使用
  • vue-cli在webpack的配置文件探究
  • 干货 | 以太坊Mist负责人教你建立无服务器应用
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • ## 基础知识
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • #预处理和函数的对比以及条件编译
  • (4)Elastix图像配准:3D图像
  • (70min)字节暑假实习二面(已挂)
  • (Forward) Music Player: From UI Proposal to Code
  • (MTK)java文件添加简单接口并配置相应的SELinux avc 权限笔记2
  • (pycharm)安装python库函数Matplotlib步骤
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (回溯) LeetCode 40. 组合总和II
  • (一)SpringBoot3---尚硅谷总结
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • ***检测工具之RKHunter AIDE
  • .mysql secret在哪_MySQL如何使用索引
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .net 获取url的方法
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • @RequestBody与@ResponseBody的使用
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [ NOI 2001 ] 食物链
  • [ 物联网 ]拟合模型解决传感器数据获取中数据与实际值的误差的补偿方法
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证