Rust 语言常见的一些概念(下)

目录

1、函数

参数

语句和表达式

具有返回值的函数

2、注释

文档注释

多行注释

3、控制流

3.1 if 表达式

3.2 使用esle if 处理多重条件

3.3 在 let 语句中使用 if

3.4 使用循环重复执行

使用 loop 重复执行代码

从循环中返回值

循环标签:在多个循环之间消除歧义

while 条件循环

使用for遍历集合


1、函数

函数在 Rust 代码中非常普遍。你已经见过语言中最重要的函数之一:main 函数,它是很多程序的入口点。你也见过 fn 关键字,它用来声明新函数。

Rust 代码中的函数和变量名使用 snake case 规范风格,也就是蛇形命名规范,跟python语言是一样的。在 snake case 中,所有字母都是小写并使用下划线分隔单词。这是一个包含函数定义示例的程序:

一个示例如下所示:

fn hello_world() {println!("hello world !")
}
fn main() {println!("main ......");hello_world()
}

注意,hello_world函数定义在 main 函数 之后;也可以定义在之前。Rust 不关心函数定义所在的位置,只要函数被调用时出现在调用之处可见的作用域内就行。它是静态语言不像其他动态(JavaScript)那样,从上往下执行,那样会找不到对应的函数。

我们可以以下以上方法,看下结果,如下所示:

参数

我们可以定义为拥有 参数parameters)的函数,参数是特殊变量,是函数签名的一部分。当函数拥有参数(形参)时,可以为这些参数提供具体的值(实参)。技术上讲,这些具体值被称为参数(arguments)。

在上面hello_world函数中,我们增加了一个参数:

fn hello_world(p: i64) {println!("hello world {p}!")
}
fn main() {println!("main ......");hello_world(1024)
}

运行以上程序,结果如下所示:

在函数签名中,必须 声明每个参数的类型。这是 Rust 设计中一个经过慎重考虑的决定:要求在函数定义中提供对用的类型说明,意味着编译器再也不需要你在代码的其他地方注明类型来指出你的意图。而且,在知道函数需要什么类型后,编译器就能够给出更有用的错误消息。

当定义多个参数时,使用逗号分隔,像这样:

fn hello_world(c: &str,p: i64,) {println!("hello world {c} {p}!")
}
fn main() {println!("main ......");hello_world("程序员的", 1024)
}

运行一下代码,如下所示:

语句和表达式

函数体由一系列的语句和一个可选的结尾表达式构成。目前为止,我们提到的函数还不包含结尾表达式,不过你已经见过作为语句一部分的表达式。因为 Rust 是一门基于表达式(expression-based)的语言,这是一个需要理解的(不同于其他语言)重要区别。其他语言并没有这样的区别,所以让我们看看语句与表达式有什么区别以及这些区别是如何影响函数体的。

语句Statements)是执行一些操作但不返回值的指令。 表达式Expressions)计算并产生一个值。让我们看一些例子。

fn main() {let x = 12345;println!("========={x}========");
}

let x = 12345; 这是一个语句。而等号后面的12345则是一个表达式。

具有返回值的函数

函数可以向调用它的代码返回值。我们并不对返回值命名,但要在箭头(->)后声明它的类型。在 Rust 中,函数的返回值等同于函数体最后一个表达式的值。使用 return 关键字和指定值,可从函数中提前返回;但大部分函数隐式的返回最后的表达式。

下面是一个具有返回值函数的示例:

fn main() {let y = y();println!("数字是:{y}")
}
fn y() -> i32 {12345
}

运行以上代码,如下所示:

y函数没有参数并定义了返回值类型,不过函数体只有单单一个 12345 也没有分号,因为这是一个表达式,我们想要返回它的值。如果加上分号,就是一个语句,就会报错了。

fn main() {let y = y();println!("数字是:{y}")
}
fn y() -> i32 {12345;
}

运行以上代码就会报以下错误:

主要的错误信息,“mismatched types”(类型不匹配),揭示了代码的核心问题。函数 y的定义说明它要返回一个 i32 类型的值,不过语句并不会返回值,使用 () 表示不返回值。因为不返回值与函数定义相矛盾,从而出现一个错误。在输出中,Rust 提供了一条信息,可能有助于纠正这个错误:它建议删除分号,这会修复这个错误。

2、注释

所有程序员都力求使其代码易于理解,不过有时还需要提供额外的解释。在这种情况下,程序员在源码中留下 注释comments),编译器会忽略它们,不过阅读代码的人可能觉得有用。

这是一个简单的注释:

// 返回一个数字
fn y() -> i32 {12345
}

文档注释

Rust 也有特定的用于文档的注释类型,通常被称为 文档注释documentation comments),它们会生成 HTML 文档。这些 HTML 展示公有 API 文档注释的内容,它们意在让对库感兴趣的程序员理解如何 使用。

以下是一个示例:

/// 返回一个数字(i32)
/// 参数:p 类型i32
/// message:......
/// 这是一个返回一个数字的函数
/// 
fn y(p:i32) -> i32 {p
}

多行注释

跟其他语言一样也可以书写多行注释,如下所示:

/*** 这是一个返回整数的方法* params: p(i32)* return: i32 */
fn y(p:i32) -> i32 {p
}

3、控制流

3.1 if 表达式

if 表达式允许根据条件执行不同的代码分支。你提供一个条件并表示 “如果条件满足,运行这段代码;如果条件不满足,不运行这段代码。”

以下是一个示例:

fn main() {let y = 1234;if y > 1024 {println!("满足条件!")} else {println!("不满足条件!")}    
}

值得注意的是代码中的条件 必须 是 bool 值。如果条件不是 bool 值,我们将得到一个错误。例如,尝试运行以下代码:

fn main() {let y = 1234;if y {println!("满足条件!")} else {println!("不满足条件!")}    
}

这个错误表明 Rust 期望一个 bool 却得到了一个整数。Rust作为一门静态语言,不会像JavaScript语言那样会进行动态的转换。

3.2 使用esle if 处理多重条件

可以使用if 和 else if 来处理多重条件的判断,以下是一个示例:

fn main() {let y = 1234;if y > 1000 {println!("大于1000!")} else if y > 100 {println!("大于100!")} else if y > 10 {println!("大于10!")} else {println!("小于于10!")}   
}

3.3 在 let 语句中使用 if

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

fn main() {let y = true;let res = if y {0} else {1};println!("res: {res}")
}

 if 的每个分支的可能的返回值都必须是相同类型,否则会报错,代码改变一下,如下所示:

fn main() {let y = true;let res = if y {0} else {false};println!("res: {res}")
}

3.4 使用循环重复执行

Rust 有三种循环:loopwhile 和 for

使用 loop 重复执行代码

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

fn main() {loop {println!("res:")}
}

当运行这个程序时,我们会看到连续的反复打印 again!,直到我们手动停止程序。大部分终端都支持一个快捷键,ctrl-c,来终止一个陷入无限循环的程序。

从循环中返回值

通过loop循环,我们可以通过break语句来中断循环,并返回结果,举一个例子,如下所示:

fn main() {let mut i = 0; let res = loop {i += 1;if i == 5 {break i * i;}};println!("res: {res}")
}

循环标签:在多个循环之间消除歧义

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

以下是一个示例:

fn main() {let mut i = 0; 'first: loop {i += 1;loop {if i % 2 == 0 {i += 1;break 'first;} else {break; }}}println!("res: {i}")
}

首先定义的可变变量i=0; 进入第一个循环的时候i+1,i的结果为1,进入到第二个循环判断i对2求余是否等于0,结果不等进入else语句块中,在else语句块出现break语句,跳出当前循环,进入到i += 1的位置,所有此时i等于2,然后再次进去第二个循环,i对2求余结果等于0,对i进行加1操作,此时i等于3,然后跳到标签循环的位置,然后往下执行打印结果:"res:3".

while 条件循环

在程序中计算循环的条件也很常见。当条件为 true,执行循环。当条件不再为 true,调用 break 停止循环。这个循环类型可以通过组合 loopifelse 和 break 来实现;

以下是一个示例:

fn main() {let mut i = 0; while i < 10 {i += 1;println!("res: {i}")}
}

使用for遍历集合

for 循环的安全性和简洁性使得它成为 Rust 中使用最多的循环结构。

下面是一个使用 for 循环的例子:

fn main() {let numbers = [10, 20, 30, 40, 50]; for i in numbers {println!("{i}")}
}

 

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

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

相关文章

【PyQt学习篇 · ⑨】:QWidget -控件交互

文章目录 是否可用是否显示/隐藏是否编辑是否为活跃窗口关闭综合案例信息提示状态提示工具提示“这是什么”提示 焦点控制单个控件角度父控件角度 是否可用 setEnabled(bool)&#xff1a;该函数用于设置QWidget控件的可用性&#xff0c;参数bool为True表示该控件为可用状态&…

08-Docker-网络管理

Docker 在网络管理这块提供了多种的网络选择方式&#xff0c;他们分别是桥接网络、主机网络、覆盖网络、MACLAN 网络、无桥接网络、自定义网络。 1-无桥接网络&#xff08;None Network&#xff09; 当使用无桥接网络时&#xff0c;容器不会分配 IP 地址&#xff0c;也不会连…

Day18力扣打卡

打卡记录 寻找重复数&#xff08;双指针&#xff09; 链接 Floyd判圈法&#xff0c;先用快慢指针以不同速率进行移动&#xff0c;最终一定会出现相遇点&#xff0c;然后在使一指针从初始开始&#xff0c;两指针再以同步调移动&#xff0c;再次相遇的点一定为循环开始的点位。 …

【计算机网络笔记】传输层——TCP特点与段结构

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

图论问题建模和floodfill算法

目录 引入&#xff1a;leetcode695.岛屿的最大面积 分析与转换 一维二维转换 四联通 完整代码解答&#xff1a; 1&#xff09;显示的创建图解决问题的代码 2&#xff09;不显示的创建图解决此问题的代码 floodfill算法 定义 引入&#xff1a;leetcode695.岛屿的最大面…

R语言用jsonlite库写的一个图片爬虫

以下是一个使用R语言和jsonlite库下载图片的程序。首先&#xff0c;我们需要导入jsonlite库和options()函数&#xff0c;然后将代理服务器的主机名和端口号设置为"duoip"和"8000"。接着&#xff0c;我们将URL设置为"https://yun.baidu.com/"&…

3dMax章鱼插件Octopus

3dMax章鱼插件Octopus 3dMax章鱼插件&#xff0c;不仅在视口中以饼状的形式&#xff0c;呼出各种属性参数&#xff0c;方便调用&#xff0c;而且是一个可编写脚本的框架&#xff0c;因此您有很多机会创建自己的菜单并轻松分发。整个OCTOPUS系统可以使用maxscript进行自定义&…

【C/C++】积累和派生类的转换

基类与派生类对象之间有赋值兼容关系&#xff0c;由于派生类中包含从基类继承的成员&#xff0c;因此可以将派生类的值赋给基类对象&#xff0c;在用到基类对象的时候可以用其子类对象代替。具体表现在以下几个方面。 一、派生类对象可以向基类对象赋值 可以用子类(即公用派生…

javaEE -15( 13000字 JavaScript入门 - 2)

一&#xff1a;JavaScript(WebAPI) JS 分成三个大的部分 ECMAScript: 基础语法部分DOM API: 操作页面结构BOM API: 操作浏览器 WebAPI 就包含了 DOM BOM&#xff0c;这个是 W3C 组织规定的. (和制定 ECMAScript 标准的大佬们不是一伙人). 前面学的 JS 基础语法主要学的是 …

3.网络之UDP

UDP协议 文章目录 UDP协议1. UDP概述2. UDP报文格式3. UDP传输限制4. UDP校验和4.1 CRC 循环冗余校验算法4.2 md5 校验算法 1. UDP概述 UDP&#xff08;UserDatagramProtocol&#xff09;是一个简单的面向消息的传输层协议&#xff0c;尽管UDP提供标头和有效负载的完整性验证&a…

【实战Flask API项目指南】之一 概述

实战Flask API项目指南之 概述 本系列文章将带你深入探索实战Flask API项目指南&#xff0c;通过跟随小菜的学习之旅&#xff0c;你将逐步掌握Flask在实际项目中的应用。让我们一起踏上这个精彩的学习之旅吧&#xff01; 前言 小菜是一个Python编程爱好者&#xff0c;他目前…

SolidWorks2022安装教程(正版)

网盘资源附文末 一.简介 SolidWorks软件是世界上第一个基于Windows开发的三维CAD系统&#xff0c;由于技术创新符合CAD技术的发展潮流和趋势&#xff0c;SolidWorks公司于两年间成为CAD/CAM产业中获利最高的公司。良好的财务状况和用户支持使得SolidWorks每年都有数十乃至数百…