Rust编程基础之条件表达式和循环

news2024/12/25 15:42:34

1.if表达式

if 表达式允许根据条件执行不同的代码分支, 以下代码是一个典型的使用if表达式的例子:

fn main() {
    let number = 3;
​
    if number < 5 {
        println!("condition was true");
    } else {
        println!("condition was false");
    }
}

所有的 if 表达式都以 if 关键字开头,其后跟一个条件。在这个例子中,条件检查变量 number 的值是否小于 5。在条件为 true 时希望执行的代码块位于紧跟条件之后的大括号中。

也可以包含一个可选的 else 表达式来提供一个在条件为 false 时应当执行的代码块,如果不提供 else 表达式并且条件为 false 时,程序会直接忽略 if 代码块并继续执行下面的代码。

尝试运行该代码, 会得到以下结果:

尝试改变 number 的值使条件为 false 时看看会发生什么:

let number = 7;

再次运行程序并查看输出:

另外值得注意的是代码中的条件 必须bool 值。如果条件不是 bool 值,我们将得到一个错误。

尝试修改代码:

fn main() {
    let number = 3;
​
    if number {
        println!("number was three");
    }
}

这里 if 条件的值是 3,Rust 抛出了一个错误:

这个错误表明 Rust 期望一个 bool 却得到了一个整数。不像 Ruby 或 JavaScript 这样的语言,Rust 并不会尝试自动地将非布尔值转换为布尔值。必须总是显式地使用布尔值作为 if 的条件。例如,如果想要 if 代码块只在一个数字不等于 0 时执行,可以把 if 表达式修改成下面这样:

fn main() {
    let number = 3;
​
    if number != 0 {
        println!("number was something other than zero");
    }
}

运行代码会打印出 number was something other than zero

2.使用else if处理多重条件

可以将 else if 表达式与 ifelse 组合来实现多重条件。看以下代码:

fn main() {
    let number = 6;
​
    if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else if number % 2 == 0 {
        println!("number is divisible by 2");
    } else {
        println!("number is not divisible by 4, 3, or 2");
    }
}

这个程序有四个可能的执行路径。运行后应该能看到如下输出:

当执行这个程序时,它按顺序检查每个 if 表达式并执行第一个条件为 true 的代码块。注意即使 6 可以被 2 整除,也不会输出 number is divisible by 2,更不会输出 else 块中的 number is not divisible by 4, 3, or 2。原因是 Rust 只会执行第一个条件为 true 的代码块,并且一旦它找到一个以后,甚至都不会检查剩下的条件了。

使用过多的 else if 表达式会使代码显得杂乱无章,所以如果有多于一个 else if 表达式,最好重构代码。

3.在let语句中使用if

因为 if 是一个表达式,我们可以在 let 语句的右侧使用它, 例如:

fn main() {
    let condition = true;
    let number = if condition { 5 } else { 6 };
​
    println!("The value of number is: {number}");
}

number 变量将会绑定到表示 if 表达式结果的值上, 运行一下查看结果:

记住,代码块的值是其最后一个表达式的值,而数字本身就是一个表达式。在这个例子中,整个 if 表达式的值取决于哪个代码块被执行。这意味着 if 的每个分支的可能的返回值都必须是相同类型;

if 分支和 else 分支的结果都是 i32 整型。如果它们的类型不匹配会发生什么?,尝试修改代码:

fn main() {
    let condition = true;
​
    let number = if condition { 5 } else { "six" };
​
    println!("The value of number is: {number}");
}

当编译这段代码时,会得到一个错误。ifelse 分支的值类型是不相容的,同时 Rust 也准确地指出在程序中的何处发现的这个问题,如图:

if 代码块中的表达式返回一个整数,而 else 代码块中的表达式返回一个字符串。这不可行,因为变量必须只有一个类型。Rust 需要在编译时就确切的知道 number 变量的类型,这样它就可以在编译时验证在每处使用的 number 变量的类型是有效的。如果number的类型仅在运行时确定,则 Rust 无法做到这一点;且编译器必须跟踪每一个变量的多种假设类型,那么它就会变得更加复杂,对代码的保证也会减少。

4.使用循环重复执行

多次执行同一段代码是很常用的,Rust 为此提供了多种 循环loops)。一个循环执行循环体中的代码直到结尾并紧接着回到开头继续执行。

Rust 有三种循环:loopwhilefor

loop 关键字告诉 Rust 一遍又一遍地执行一段代码直到你明确要求停止。

fn main() {
    loop {
        println!("again!");
    }
}

当运行这个程序时,我们会看到连续的反复打印 again!,直到我们手动停止程序。大部分终端都支持一个快捷键,ctrl-c,来终止一个陷入无限循环的程序。Rust跟其它高级语言一样,叶提供了break关键字停止循环,使用continue关键字告诉程序跳过这个循环迭代中的任何剩余代码,并转到下一个迭代。

loop 的一个用例是重试可能会失败的操作,比如检查线程是否完成了任务。然而你可能会需要将操作的结果传递给其它的代码。如果将返回值加入你用来停止循环的 break 表达式,它会被停止的循环返回, 看看下面的代码:

fn main() {
    let mut counter = 0;
​
    let result = loop {
        counter += 1;
​
        if counter == 10 {
            break counter * 2;
        }
    };
​
    println!("The result is {result}");
}

在循环之前,我们声明了一个名为 counter 的变量并初始化为 0。接着声明了一个名为 result 来存放循环的返回值。在循环的每一次迭代中,我们将 counter 变量加 1,接着检查计数是否等于 10。当相等时,使用 break 关键字返回值 counter * 2。循环之后,我们通过分号结束赋值给 result 的语句。最后打印出 result 的值,也就是 20

如果存在嵌套循环,breakcontinue 应用于此时最内层的循环。你可以选择在一个循环上指定一个 循环标签loop label),然后将标签与 breakcontinue 一起使用,使这些关键字应用于已标记的循环而不是最内层的循环。看以下代码:

fn main() {
    let mut count = 0;
    'counting_up: loop {
        println!("count = {count}");
        let mut remaining = 10;
​
        loop {
            println!("remaining = {remaining}");
            if remaining == 9 {
                break;
            }
            if count == 2 {
                break 'counting_up;
            }
            remaining -= 1;
        }
​
        count += 1;
    }
    println!("End count = {count}");
}

外层循环有一个标签 counting_up,它将从 0 数到 2。没有标签的内部循环从 10 向下数到 9。第一个没有指定标签的 break 将只退出内层循环。break 'counting_up; 语句将退出外层循环。运行结果如下:

5.while循环

在程序中计算循环的条件也很常见。当条件为 true,执行循环。当条件不再为 true,调用 break 停止循环。这个循环类型可以通过组合 loopifelsebreak 来实现。然而,这个模式太常用了,Rust 为此内置了一个语言结构,它被称为 while 循环。看以下代码:

fn main() {
    let a = [10, 20, 30, 40, 50];
    let mut index = 0;
​
    while index < 5 {
        println!("the value is: {}", a[index]);
​
        index += 1;
    }
}

这里,代码对数组中的元素进行计数。它从索引 0 开始,并接着循环直到遇到数组的最后一个索引(这时,index < 5 不再为真)。运行这段代码会打印出数组中的每一个元素,如图:

数组中的所有五个元素都如期被打印出来。尽管 index 在某一时刻会到达值 5,不过循环在其尝试从数组获取第六个值(会越界)之前就停止了。

但这个过程很容易出错;如果索引长度或测试条件不正确会导致程序 panic。例如,如果将 a 数组的定义改为包含 4 个元素而忘记了更新条件 while index < 4,则代码会 panic。这也使程序更慢,因为编译器增加了运行时代码来对每次循环进行条件检查,以确定在循环的每次迭代中索引是否在数组的边界内。

作为更简洁的替代方案,可以使用 for 循环来对一个集合的每个元素执行一些代码。改造后的代码如下:

fn main() {
    let a = [10, 20, 30, 40, 50];
​
    for element in a {
        println!("the value is: {element}");
    }
}

当运行这段代码时,将看到与while循环中一样的输出。更为重要的是,我们增强了代码安全性,并消除了可能由于超出数组的结尾或遍历长度不够而缺少一些元素而导致的 bug。

for 循环的安全性和简洁性使得它成为 Rust 中使用最多的循环结构。下面是一个使用 for 循环来倒计时的例子,它还使用了一个方法,rev,用来反转 range:

fn main() {
    for number in (1..4).rev() {
        println!("{number}!");
    }
    println!("LIFTOFF!!!");
}

执行结果如图:

是不是感觉有点点帅气了?

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

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

相关文章

win10 + vs2017 + cmake3.17编译OSG-3.4.1

参考教程&#xff1a;https://blog.csdn.net/bailang_zhizun/article/details/120992244 1. 下载与解压 2. 修改configure 1&#xff09;Ungrouped Entries -- 》ACTUAL_3RDPARTY_DIR: 设置为&#xff1a; D:/Depend_3rd_party/OSG341/3rdParty 2&#xff09; Ungrouped E…

免费的 AI 视频生成工具 Moonvalley 厉害了!Moonvalley 怎么用(保姆级教程)

一、Moonvalley 介绍 Moonvalley&#xff0c;号称地表最强的 AI 视频生成工具&#xff0c;到底有多厉害&#xff1f;今天一起来看一下~ 这是 Moonvalley 官网的介绍&#xff1a; Moonvalley 是一个开创性的新型文本到视频的生成式 AI 模型。用简单的文本即可创建出惊人的电影和…

分享一个自己写的免费的微信聊天记录提取软件 2023.11.03

有什么办法可以导出与某个人的微信聊天记录&#xff1f; 只想导出与某个微信好友的聊天记录&#xff0c;有办法做到吗&#xff1f;导出所有的话&#xff0c;文件太大了&#xff0c;只想导出与其中一个人的&#xff0c;求大神教。 我的需求和上面这个人的比较类似&#xff0c;因…

2023辽宁省数学建模竞赛选题建议及AB题思路

大家好呀&#xff0c;今天早上2023年辽宁省大学生数学建模竞赛开赛&#xff0c;在这里给大家带来初步的选题建议及思路。 注意&#xff0c;本文只是比较简略的图文版讲解&#xff0c;完整的视频版讲解请移步&#xff1a; 2023辽宁省数学建模竞赛选题建议及初步思路_哔哩哔哩_…

【面经】讲一下synchronized锁升级的过程

synchronized锁升级是指从偏向锁到轻量级锁&#xff0c;再到重量级锁的过程。 当线程获取synchronized对象时&#xff0c;首先会进行偏向锁的尝试。 如果偏向锁没有竞争&#xff0c;线程将永远不需要同步。 但是&#xff0c;如果偏向锁竞争失败&#xff0c;将升级到轻量级锁。…

python自动化测试模板

1:准备html模版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>接口自动化…

数据库管理-第114期 Exadata 05-ESS-上(202301103)

数据库管理-第114期 Exadata 05-ESS-上&#xff08;202301103&#xff09; 之前提到过&#xff0c;Exadata通过ESS将存储转换为了智能存储&#xff0c;其实相较于纸面参数非常牛逼但性能还是比不过Exadata的国产一体机&#xff0c;最大的差距也就是在ESS上&#xff0c;从数据库…

自动化测试如何准备测试数据

其实大部分类型的测试都需要去准备测试数据。 手工测试&#xff1a;一些基础数据&#xff0c;比如配置数据等等是需要去准备的&#xff1b;自动化测试&#xff1a;基础需要准备&#xff0c;现有数据&#xff0c;动态运行时产生的数据是需要准备的&#xff1b;性能测试&#xf…

华为云API Explorer伙伴招募火热进行中~

API编排新特性助力伙伴 零代码构建API工作流 实现快速集成场景编排能力 面向三大核心场景&#xff1a; API调用逻辑频繁改动 API间高耦合不便管理 复杂API解决方案难构建 伙伴加入可立享四大限时福利&#xff1a; 免费试用、专家咨询、技术指导、生态支持 点此报名>&…

XSpirit 2智能边缘计算机使用测评

博客主页&#xff1a;https://tomcat.blog.csdn.net 博主昵称&#xff1a;农民工老王 主要领域&#xff1a;Java、Linux、K8S 期待大家的关注&#x1f496;点赞&#x1f44d;收藏⭐留言&#x1f4ac; 目录 拆箱过程介绍视频使用感受 我之前就参加过 Spirit 1 第一代智能边缘计…

Web自动化测试 —— PageObject设计模式!

一、page object 模式简介 1.1、传统 UI 自动化的问题 无法适应 UI 频繁变化无法清晰表达业务用例场景大量的样板代码 driver/find/click 二、page object 设计原则 2.1、POM 模式的优势 降低 UI 变化导致的测试用例脆弱性问题让用例清晰明朗&#xff0c;与具体实现无关 2.…

人工智能AI创作系统ChatGPT网站系统源码+AI绘画系统支持GPT4.0/支持Midjourney局部重绘

一、前言 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建…

压缩软件 7-Zip VS WinZips

7-zip在联想应用商店给强烈推荐&#xff1f; 要说它好用还行&#xff0c;但每次压缩都显示网络连接失败等异常广告信息。 相反好用的7-ZIP必须鼠标点击右键点击更多才能够看到&#xff0c;这次更新体验也太差了吧&#xff1f; 用户放在第一位&#xff1f; 要不是更新后一直推…

【技术分享】RK356X Android 使用 libgpiod 测试gpio

前言 libgpiod 是用于与 Linux GPIO 字符设备交互的 C 库和工具库&#xff1b;此项目包含六种命令行工具&#xff08;gpiodetect、gpioinfo、gpioset、gpioget、gpiomon&#xff09;&#xff0c;使用这些工具可以在命令行设置和获取GPIO的状态信息&#xff1b;在程序开发中也可…

Python库学习(十二):数据分析Pandas[下篇]

接着上篇《Python库学习(十一):数据分析Pandas[上篇]》,继续学习Pandas 1.数据过滤 在数据处理中&#xff0c;我们经常会对数据进行过滤&#xff0c;为此Pandas中提供mask()和where()两个函数&#xff1b; mask(): 在 满足条件的情况下替换数据&#xff0c;而不满足条件的部分…

BUUCTF 另外一个世界 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 下载附件&#xff0c;解压得到一个.jpg图片。 密文&#xff1a; 解题思路&#xff1a; 1、这道题我尝试了很多方法&#xff0c;知道看了别人的wp才知道flag在我忽略的地方。将图片在010 Editor中打开&#xff0c;从…

Redis学习系统(持续更新中)

RedisExample 课程介绍 目标是提供一个高效、可靠的学习和实践Redis的环境。我们将通过搭建Redis集群、实现缓存数据的持久化存储、制定缓存数据的淘汰策略以及同步缓存数据等步骤来深入了解和学习Redis的特性和功能。通过这个项目&#xff0c;你可以掌握Redis的核心概念和技…

vue+asp.net Web api前后端分离项目发布部署

一、前后端项目介绍 1.前端项目是使用vue脚手架进行创建的。 脚手架版本&#xff1a;vue/cli 5.0.8 编译器版本&#xff1a;vs code 1.82.2 2.后端是一个asp.net Core Web API 项目 后端框架版本&#xff1a;.NET 6.0 编译器版本&#xff1a;vs 2022 二、发布部署步骤 第…

预处理详解(二)

1.宏和函数对比 宏通常被应用于执行简单的运算。 比如在两个数中找出较大的一个。 #define MAX(a, b) ((a)>(b)?(a):(b)) 那为什么不用函数来完成这个任务&#xff1f; 原因有二&#xff1a; 1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所…

C++笔记之实现多态的所有方法

C笔记之实现多态的所有方法 文章目录 C笔记之实现多态的所有方法1.C中多态是是什么&#xff1f;请用简洁准确的话描述2.虚函数实现多态2.1.虚函数&#xff08;Virtual Functions&#xff09;2.2.纯虚函数&#xff08;Pure Virtual Functions&#xff09;2.3.虚析构函数&#xf…