Rust语言入门第七篇-控制流

news2024/9/21 2:28:49

文章目录

  • Rust语言入门第七篇-控制流
    • If 表达式
      • 基本结构
      • 特点和规则
      • 示例
    • let 语句中使用 if
    • loop 循环
        • 基本结构
        • 特点
        • 示例
        • 综合示例
    • while 循环
        • 基本结构
        • 特点
        • 示例
        • 综合示例
      • 与 `loop` 循环的区别
    • for 循环
        • 基本结构
        • 详细说明
        • 特点
        • 示例
        • 综合示例
    • match 表达式
      • `match`表达式的语法结构
        • 示例代码

Rust语言入门第七篇-控制流

Rust 的控制流是指程序执行过程中根据不同的条件选择不同的代码路径的能力。这是编程中一个核心的概念,帮助开发者实现逻辑判断、循环执行等基本结构。Rust 语言提供了一些关键的控制流构造,主要包括 if 表达式、match 表达式、loop、while、for 循环等。

If 表达式

if表达式在很多语言中很常见!if表达式允许条件不同执行不同的代码。

Rust 语言中的 if 表达式用于基于条件来执行不同的代码块。它的结构相对直接,但有几个特点需要注意,这些特点体现了 Rust 作为一门类型安全和表达式导向语言的特性。以下是 if 表达式的基本结构和一些关键点:

基本结构

if 条件 {
    // 当条件为 true 时执行的代码块
} else {
    // 当条件为 false 时执行的代码块(可选)
}

特点和规则

  1. 条件必须是布尔类型 (bool):与某些其他语言不同,Rust 不会隐式地将非布尔类型的值转换为布尔值。你需要确保 if 后面的条件表达式直接评估为一个布尔值。

  2. 代码块 ({}):即使 ifelse 分支只包含一条语句,你也必须使用花括号 {} 将其包裹起来。这是为了保持一致性,并且因为 Rust 中几乎所有东西都是表达式。

  3. 可选的 else if:为了实现多路分支,你可以链式使用 else if 语句。

if 条件1 {
    // 当条件1为 true 时执行
} else if 条件2 {
    // 当条件1为 false 并且条件2为 true 时执行
} else {
    // 当以上所有条件都为 false 时执行
}
  1. 表达式 vs. 语句:在 Rust 中,if 表达式实际上是一个表达式,这意味着它有返回值。每个分支的最后一项(即最后一个表达式的值)决定了整个 if 表达式的值。这使得 if 表达式可以在需要值的上下文中使用,比如赋值给变量或作为函数的返回值。

示例

fn calculate_result(score: i32) -> &'static str {
    if score > 90 {
        "Excellent"
    } else if score > 75 {
        "Good"
    } else {
        "Keep trying"
    }
}

fn main() {
    let score = 85;
    let result = calculate_result(score);
    println!("{}", result); // 输出 "Good"
}

在这个示例中,calculate_result 函数根据分数返回不同的评价等级,展示了 if 表达式如何用作返回值的计算。

let 语句中使用 if

在 Rust 中,结合 let 和 if 一起使用的结构被称为 if let 表达式。这是一种简化版的 match 表达式,专门用于处理单一的模式匹配情况

fn main() {
    let condition = true;
    let number = if condition { 5} else { 6 };
    println!("数字的值为:{number}");   
}

在这里插入图片描述

这段 Rust 代码演示了如何使用 if 表达式作为值赋给变量,体现了 Rust 中 if 表达式不仅用于控制流,还可以直接产生值的特性。下面是详细的解释:

  1. 初始化变量 condition: 首先,定义了一个布尔型变量 condition 并将其值设为 true

    let condition = true;
    
  2. 使用 if 表达式赋值给 number: 接下来,定义了一个变量 number,其值由一个 if 表达式决定。这个 if 表达式检查 condition 的值:

    • 如果 conditiontrue,则执行 { 5 } 代码块,表达式的值为 5
    • 如果 conditionfalse,则执行 { 6 } 代码块,表达式的值为 6

    这里,if 表达式直接充当了一个值生成器,其结果(56)被赋给了 number

    let number = if condition { 5 } else { 6 };
    

loop 循环

loop 是 Rust 中的一种循环结构,它没有内置的终止条件,因此会一直执行循环体内的代码,直到遇到 break 语句为止。这对于需要无限循环或循环次数未知的情况非常有用。

基本结构
loop {
    // 循环体内的代码
    // 使用 break 语句来退出循环
}
特点
  1. 无终止条件loop 没有内置的终止条件,这意味着它会一直运行,直到你显式地使用 break 语句来停止它。
  2. 使用 break 退出:要终止 loop 循环,你必须在循环体内使用 break 语句。
  3. 使用 continue 跳过迭代:你也可以使用 continue 语句来跳过当前迭代,并立即开始下一次迭代。
示例

下面是一个简单的 loop 循环示例,该示例将会数到 10 并打印出每个数字。当计数达到 10 时,使用 break 语句退出循环。

fn main() {
    let mut count = 0;

    loop {
        println!("Count: {}", count);

        count += 1;
        if count == 10 {
            break;
        }
    }
}
综合示例

下面是一个稍微复杂的例子,该示例使用 loop 来模拟一个简单的游戏,玩家可以选择继续游戏或退出。

use std::io;

fn main() {
    let mut choice = 'y';

    loop {
        println!("Welcome to the game!");
        println!("Do you want to play? (y/n)");

        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .expect("Failed to read line");
        choice = input.trim().chars().next().unwrap_or('n');

        if choice == 'y' {
            println!("Playing...");
        } else {
            println!("Exiting...");
            break;
        }
    }
}

在这个示例中:

  • 我们定义了一个变量 choice 来存储用户的输入。
  • 使用 loop 来重复询问用户是否想继续玩游戏。
  • 使用 std::io::stdin().read_line() 来读取用户的输入。
  • 使用 break 语句来结束循环,当用户输入 ‘n’ 时。

这个示例展示了如何使用 loop 来构建一个无限循环,并通过用户输入来控制循环的终止。

while 循环

基本结构
while condition {
    // 当条件为 true 时执行的代码块
}
特点
  • while 循环会在每次迭代前检查给定的条件。
  • 如果条件为 true,则执行循环体内的代码。
  • 如果条件为 false,则不执行循环体内的代码,并且循环终止。
  • loop 相比,while 循环提供了内置的终止条件,这使得它适合于那些你知道循环应该执行多少次或何时应停止的情况。
  • 在循环体内部,你可以使用 break 语句来提前终止循环。
  • 你也可以使用 continue 语句来跳过当前迭代并开始下一次迭代。
示例

下面是一个简单的 while 循环示例,该示例将会数到 10 并打印出每个数字。

fn main() {
    let mut count = 0;
    while count < 10 {
        println!("Count: {}", count);
        count += 1;
    }
}
综合示例

下面是一个稍微复杂的例子,该示例使用 while 循环来模拟一个简单的游戏,玩家可以选择继续游戏或退出。

use std::io;

fn main() {
    let mut choice = 'y';

    while choice == 'y' {
        println!("Welcome to the game!");
        println!("Do you want to play? (y/n)");

        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .expect("Failed to read line");
        choice = input.trim().chars().next().unwrap_or('n');

        if choice == 'y' {
            println!("Playing...");
        } else {
            println!("Exiting...");
        }
    }
}

在这个示例中:

  • 我们定义了一个变量 choice 来存储用户的输入。
  • 使用 while 来重复询问用户是否想继续玩游戏,只要 choice'y'
  • 使用 std::io::stdin().read_line() 来读取用户的输入。
  • 用户可以通过输入 'n' 来退出游戏,此时 choice 变为 'n'while 循环的条件变为 false,循环终止。

loop 循环的区别

  • while 循环在每次迭代之前检查条件是否为 true,而 loop 没有内置的终止条件。
  • while 循环适合于那些你知道循环应该执行多少次或何时应停止的情况,而 loop 更适用于不知道循环次数的情况。
  • while 循环中,如果初始条件就是 false,那么循环体内的代码将不会被执行;而在 loop 循环中,你必须显式地使用 break 语句来终止循环。

for 循环

基本结构
for variable in iterable {
    // 循环体内的代码
}
详细说明
  • for 关键字:开始 for 循环。
  • variable:循环变量,用于保存每次迭代中的当前元素。这可以是任意有效的 Rust 标识符。
  • in 关键字:表示循环变量将在接下来的迭代中遍历的集合或范围。
  • iterable:可以被迭代的对象,它可以是实现了 IntoIterator 特性的任何类型,例如向量 (Vec<T>), 数组 ([T; N]), 字符串 (String&str), 范围 (a..ba..=b) 等。
  • { ... }:花括号包围的代码块,称为循环体。这里包含了每次迭代要执行的代码。
特点
  • 自动迭代for 循环会自动迭代 iterable 中的每个元素,并在每次迭代时将当前元素绑定到 variable
  • 类型推断:编译器会自动推断 variable 的类型,使其与 iterable 中的元素类型相匹配。
  • 范围迭代:可以使用范围来指定一个数值序列,例如 0..10 代表从 0 到 9 的整数序列。
  • 引用迭代:默认情况下,for 循环迭代的是 iterable 中元素的引用,这意味着原始数据结构不会被修改。如果你想获得元素的所有权,可以使用 .into_iter() 方法。
  • 可变迭代:如果你想在迭代过程中修改元素,可以使用 iter_mut() 方法来获取可变引用。
示例

下面是一个简单的 for 循环示例,该示例将会遍历一个向量并打印出每个元素。

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    for number in &numbers {  // 迭代向量中的元素引用
        println!("Number: {}", number);
    }

    for number in numbers.into_iter() {  // 迭代向量中的元素所有权
        println!("Number: {}", number);
    }

    // 使用范围迭代
    for i in 0..10 {
        println!("i: {}", i);
    }
}
综合示例

下面是一个稍微复杂的例子,该示例使用 for 循环来遍历一个字符串,并统计其中每个字符出现的次数。

use std::collections::HashMap;

fn main() {
    let text = "hello world";
    let mut char_counts = HashMap::new();

    for c in text.chars() {  // 遍历字符串中的字符
        let count = char_counts.entry(c).or_insert(0);
        *count += 1;
    }

    for (char, count) in &char_counts {  // 遍历 HashMap 中的键值对
        println!("'{}': {}", char, count);
    }
}

在这个示例中:

  • 我们定义了一个字符串 text
  • 使用 for 循环来遍历字符串中的每个字符。
  • 使用 HashMap 来记录每个字符出现的次数。
  • 使用 entry 方法来获取或创建一个条目,然后增加计数。
  • 最后再次使用 for 循环来遍历 HashMap 并打印每个字符及其对应的计数。

match 表达式

Rust语言中的match表达式是模式匹配的一种方式,用于在多个分支中选择一个执行。它类似于其他编程语言中的switch语句,但是功能更加强大和灵活,可以匹配复杂的模式而不仅仅是整数或字符串值。

match表达式的语法结构

基本的match表达式的语法如下:

match value {
    pattern if guard_condition => expression,
    // 更多的 pattern...
    _ => default_expression, // 可选的默认分支
}
  • value 是你要匹配的值。
  • pattern 是你想要匹配的模式。
  • if guard_condition 是一个可选的条件,只有当这个条件为真时,模式才匹配。
  • expression 是如果模式匹配成功后要执行的代码块。
  • _ 是一个通配符模式,表示如果没有其他模式匹配成功,则执行default_expression

注意:所有可能的情况都必须被覆盖,要么显式地处理,要么通过使用通配符_来提供一个默认分支。如果不能覆盖所有情况,编译器将会报错。

示例代码
// 定义一个枚举类型UsState,这里只列举了两个州作为示例
enum UsState {
    Alabama,
    Alaska,
}

// 定义一个函数say_hello,接收一个UsState类型的参数state
fn say_hello(state: UsState) {
    // 使用match表达式来匹配传入的state值
    match state {
        // 如果state是Alabama,则打印"Let's go to the beach!"
        UsState::Alabama => println!("Let's go to the beach!"),
        // 如果state是Alaska,则打印"Maybe visit the glaciers?"
        UsState::Alaska => println!("Maybe visit the glaciers?"),
        // 如果没有其他模式匹配成功(即state不是Alabama也不是Alaska),则打印"Some other state."
        _ => println!("Some other state."),
    }
}

// 主函数,程序的入口点
fn main() {
    // 创建一个UsState枚举实例
    let current_state = UsState::Alabama;
    // 调用say_hello函数并传入当前的州
    say_hello(current_state);
}
// 定义一个名为calculate_length的函数,接收一个包含两个i32值的元组作为参数
fn calculate_length(x: (i32, i32)) -> String {
    // 使用match表达式来匹配元组x中的元素
    match x {
        // 如果元组的第一个元素和第二个元素都是0,则返回"Origin"
        (0, 0) => String::from("Origin"), // 这里使用String::from方法创建一个新的字符串
        // 如果元组的第一个元素是0但第二个元素不是0,则格式化并返回一个字符串
        (0, y) => format!("On the Y axis at {}", y), // format!宏用于创建格式化的字符串
        // 如果元组的第二个元素是0但第一个元素不是0,则格式化并返回一个字符串
        (x, 0) => format!("On the X axis at {}", x), // format!宏用于创建格式化的字符串
        // 如果元组的两个元素都不是0,则格式化并返回一个包含两个坐标值的字符串
        (x, y) => format!("({}, {})", x, y), // format!宏用于创建格式化的字符串
    }
}

// 主函数,程序的入口点
fn main() {
    // 创建一个包含两个i32值的元组
    let coordinates = (3, 4);
    // 调用calculate_length函数并传入坐标值
    let length = calculate_length(coordinates);
    // 打印返回的字符串
    println!("{}", length); // 输出"(3, 4)"
}

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

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

相关文章

Mysql存储过程详细解读

目录 存储过程介绍 创建与调用 查看与删除 变量 系统变量 用户自定义变量 ​编辑局部变量 ​编辑​编辑IF判断 存储过程参数​编辑​编辑​编辑 CASE ​编辑 WHILE​编辑 ​编辑REPEAT​编辑​编辑 LOOP 游标 条件处理程序 存储函数 存储过程介绍 创建与调用 查…

GNN-RAG:用于大模型推理的图神经检索

GNN-RAG&#xff1a;用于大模型推理的图神经检索 秒懂大纲提出背景解法拆解全流程优化创意总结 论文&#xff1a;GNN-RAG: Graph Neural Retrieval for Large Language Model Reasoning 代码&#xff1a;https://github.com/cmavro/GNN-RAG 秒懂大纲 ├── GNN-RAG【主题】…

【刷题日记】43. 字符串相乘

43. 字符串相乘 其实就是大数乘法题&#xff0c;这道题用草稿纸演练一下&#xff0c;其实很好找到方法&#xff0c;模拟大数乘法即可。需要注意的是进位和迭代值&#xff0c;还有注意向下取整和去除前导0&#xff08;容易遗漏&#xff09;。去除前导0的时候还要注意如果全是0&…

命令行运行python时找不到模块怎么解决

问题&#xff1a; 新建了一个项目&#xff0c;目录结构如下&#xff1a; 然后在pycharm中运行glovar是没有问题的&#xff0c;但是在命令行中运行就会提示找不到init模块。 这是因为在pycharm中运行的时候&#xff0c;pycharm会自动将项目所在目录添加到了sys.path中&#xf…

天宝Trimble RealWorks2024.0.2注册机 点云后处理软件 点云三维重建软件

一、功能特色 1、强大的点云数据处理平台 Trimble Realworks2024是市面上先进的点云数据处理软件&#xff0c;能够配准、可视化、浏览和直接处理市面上几乎所有主流品牌扫描仪点云数据&#xff0c;包括Leica、Riegl、ZF、Faro、Topcon等。 2、业界领先的无目标全自动配准 T…

Apache Flink 流批融合技术介绍

摘要&#xff1a;本文整理自阿里云高级研发工程师、Apache Flink Contributor 周云峰老师在 Apache Asia CommunityOverCode 2024中的分享。内容主要分为以下三个部分&#xff1a; 从流批一体到流批融合流批融合的技术解决方案社区进展及未来展望 一、从流批一体到流批融合 1&…

记忆化搜索专题——算法简介力扣实战应用

目录 1、记忆化搜索算法简介 1.1 什么是记忆化搜索 1.2 如何实现记忆化搜索 1.3 记忆化搜索与动态规划的区别 2、算法应用【leetcode】 2.1 题一&#xff1a;斐波那契数 2.1.1 递归暴搜解法代码 2.1.2 记忆化搜索解法代码 2.1.3 动态规划解法代码 2.2 题二&#xff1…

网络模型的保存与读取

文章目录 一、模型的保存二、文件的加载三、模型加载时容易犯的陷阱 一、模型的保存 方式1:torch.save(vgg16, “vgg16_method1.pth”) import torch import torchvision.modelsvgg16 torchvision.models.vgg16(pretrainedFalse) torch.save(vgg16, "vgg16_method1.pth…

oracle数据库启动

文章目录 背景一、步骤1.登录oracle用户2.启动监听服务3.启动数据库 背景 oracle数据库启动 一、步骤 1.登录oracle用户 代码如下&#xff08;示例&#xff09;&#xff1a; su - oracle2.启动监听服务 代码如下&#xff08;示例&#xff09;&#xff1a; lsnrctl start成…

【C++】STL----vector常见用法

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;C从小白到高手 &#x1f339;往期回顾&#x1f339;&#xff1a;[C]string类 &#x1f516; 流水不争&#xff0c;争的是滔滔不息。 文章目录 一、vector的介绍vector…

MATLAB绘图基础8:双变量图形绘制

参考书&#xff1a;《 M A T L A B {\rm MATLAB} MATLAB与学术图表绘制》(关东升)。 8.双变量图形绘制 8.1 散点图 散点图用于显示两个变量间的关系&#xff0c;每个数据点在图上表示为一个点&#xff0c;一个变量在 X {\rm X} X轴&#xff0c;一个变量在 Y {\rm Y} Y轴&#…

【Python报错已解决】AttributeError: ‘DataFrame‘ object has no attribute ‘append‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

暴雨信息|《2024 年全球人工智能趋势报告》发布,GPU仍是AI发展最大关键之一

全球著名调研机构WEKA近日正式发布《2024年全球人工智能趋势报告》&#xff0c;该报告是基于全球1500人工智能决策者的深度调查&#xff0c;覆盖金融、政府、医疗保健等多个行业&#xff0c;解锁了人工智能领域的关键见解和策略。 人工智能正成为许多组织战略的一个基本面&…

滑动窗口(8)_最小覆盖字串

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 滑动窗口(8)_最小覆盖字串 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. 题…

6.C++程序中的基本数据类型

数据类型是指在C中用于声明不同类型变量或函数的一个系统或抽象或者是一个分类&#xff0c;它决定了变量存储占用的内存空间以及解析存储的位模式。其实数据类型可以理解为固定内存大小的别名&#xff0c;是创建变量的模具&#xff0c;具体使用哪种模具&#xff08;包括自定义&…

基于深度学习的文本情感原因提取研究综述——论文阅读

前言 既然要学习情感分析&#xff0c;那么肯定还要了解情感原因对抽取的发展历程&#xff0c;所以我又搜了一篇研究综述&#xff0c;虽然是2023年发表的&#xff0c;但是里面提及到的历程仅停留到2022年。这篇综述发布在TASLP期刊&#xff0c;是音频、声学、语言信号处理的顶级…

进程间的通信-信号量

信号量 1.资源竞争 资源竞争 : 当多个进程同时访问共享资源时&#xff0c;会产生资源竞争&#xff0c;最终最导致数据混乱临界资源 : 不允许同时有多个进程访问的资源&#xff0c;包括硬件资源(CPU、内存、存储器以及其他外围设备)与软件资源(共享代码段、共享数据结构)临界区…

有关JS下隐藏的敏感信息

免责声明&#xff1a;本文仅做分享&#xff01; 目录 JavaScript 介绍 核心组成 工具 FindSomething ** 浏览器检查 ** LinkFinder URLfinder ** SuperSearchPlus ** ffuf ParasCollector waymore Packer Fuzzer JS逆向 应用&#xff1a; 小结&#xff1a; Ja…

基于Python+SQLite的课程管理系统

系统需求简介 1.1需求分析 实现一个具体的课程管理系统。按照软件工程思路设计简化的专业课数据库&#xff0c;尽量模拟现有专业课程一个学期的选课排课原型实际情况。&#xff08;注&#xff1a;本系统由本人单独设计、开发完成&#xff09; 1.2 数据结构需求分析 课程管理…

NAND闪存:迎来新的发展机遇

2024年&#xff0c;存储市场正在经历着动态的变化&#xff0c;其中包括合同价格的上涨、制造商营收的增长以及多项技术上的突破。在这个背景下&#xff0c;主要的存储公司正在为新的挑战做准备&#xff0c;尤其是在NAND闪存领域即将面临转型的情况下。 扩展阅读&#xff1a;20…