Rust 基础系列 #7: 在 Rust 中使用循环
创始人
2024-03-02 16:02:35
0

在 Rust 系列的 上一篇文章 中,我介绍了如何使用 ifelse 关键字来处理 Rust 程序的控制流。

这是处理程序控制流的一种方法。另一种方法是使用循环。因此,让我们在本文中看看循环。

Rust 中可用的循环

Rust 编程语言有三种不同的循环,基于你想要实现什么以及可用的内容:

  • for
  • while
  • loop

我假设你对 forwhile 已经很熟悉了,但 loop 对你来说可能是个新概念。让我们先从熟悉的概念开始。

for 循环

for 循环主要用于迭代一种称为迭代器的东西。

这个迭代器可以从任何东西中创建,从数组、向量(很快就会介绍!)、一系列值,或者任何自定义的东西。这里的可能性是无限的。

来看看 for 循环的语法。

for 迭代变量 in 迭代器 {
    <语句>;
}

其中的 迭代变量 在大多数其他编程语言教程中通常被称为 i ; )

迭代器 可以是任何东西,只要它能告诉下一个值是什么,如果有的话。

来通过一个程序来理解这个。

fn main() {
    let my_arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

    println!("迭代数组");
    for element in my_arr {
        println!("{}", element);
    }

    println!("\n迭代一个真正的迭代器");
    for element in my_arr.iter() {
        println!("{}", element);
    }

    println!("\nPython 风格的范围");
    for element in 0..10 {
        println!("{}", element);
    }
}

这里,我声明了一个数组,它包含从 0 到 9 的 10 个数字。在第 5 行的 for 循环中,我只是将这个数组指定为迭代器,Rust 会自动处理对这个数组的所有元素的迭代。不需要花哨的 my_arr[i] 魔法。

但是,在第 10 行,我调用了 .iter() 函数。这是一个明确的提及,它基于 my_arr 的值来获取一个迭代器。这个循环和第 5 行的循环之间唯一的区别是,这里你是通过在数组上调用 .iter() 函数来明确地调用它的。

在这个上下文环境中,在一个数据类型上调用 .iter() 函数不是必须的。因为这是一个数组,是语言本身提供的一种数据类型,Rust 已经知道如何处理它了。但是你 需要 在自定义数据类型中使用它。

最后,在第 15 行,我们有一个循环,它循环遍历一个范围。嗯,差不多是这样。如果你仔细看,这个范围看起来很像切片 “类型”。Rust 也知道这一点,并且 你处理了迭代(哈哈,明白了吗?)。

LCTT 译注:此处的梗是,“为你处理了迭代” 的英文原文是 “handles iteration for you",其中的 “for” 与 “for 循环” 的 “for” 是同一个单词。

输出如下:

迭代数组
0
1
2
3
4
5
6
7
8
9

迭代一个真正的迭代器
0
1
2
3
4
5
6
7
8
9

Python 风格的范围
0
1
2
3
4
5
6
7
8
9

while 循环

while 循环可以被认为是非常类似于 if 条件语句。使用 if 语句,只要用户提供的条件为 trueif 语句体中的代码就会被执行 一次

但是,在 while 循环中,如果条件评估为 true,循环就会开始循环循环体。只要条件继续评估为 true,循环就会继续迭代。

while 循环只有在循环完成当前迭代中所有语句的执行并且在检查条件时,它的结果为 false 时才会停止。

来看看 while 循环的语法…

while 条件 {
    <语句>;
}

看到了吗?和 if 条件语句非常相似!不过没有 else 块 ; )

来看一个程序来更好地理解这个。

fn main() {
    let mut var = 0;

    while var < 3 {
        println!("{var}");
        var += 1;
    }
}

我有一个可变变量 var,它的初始值为 0。只要可变变量 var 中存储的值小于 3,while 循环就会执行。

在循环中,var 的值被打印出来,然后它的值被增加 1。

这是上面代码的输出:

0
1
2

loop 循环

Rust 有一个无限循环。是的,一个没有开始条件和停止条件的循环。它只是一直循环,直到永远。当然,它有触发器来停止代码本身的循环执行。

无限循环的语法如下:

loop {
    <语句>;
}

? 这些循环主要用于 GUI 软件,退出是一个 显式 操作。

在我给你一个例子之前,因为这个循环非常特殊,让我们先看看如何 退出 它 :p

要停止无限循环的执行,需要在循环内使用 break 关键字。

来看一个例子,只有 0 到 3 之间的整数(包括 0 和 3)才会被打印到程序输出。

fn main() {
    let mut var = 0;

    loop {
        if var > 3 {
            break;
        }

        println!("{}", var);
        var += 1;
    }
}

看待这个特定的例子的最好方法是将它看作是一个增加了一堆没有必要的东西的 while 循环 ; )

你有一个可变变量 var,它的初始值为 0,它被用作迭代器。无限循环从一个 if 条件开始,如果 var 的值大于 3,break 关键字就会被执行。后来,就像 while 循环的前一个例子一样,var 的值被打印到标准输出,然后它的值被增加 1。

它的输出如下:

0
1
2
3

标记循环

假设有两个无限循环,一个嵌套在另一个中。由于某种原因,退出条件在最内层循环中被检查,但这个退出条件是为了退出最外层循环。

在这种情况下,标记循环可能是有益的。

? breakcontinue 关键字并不仅仅用于无限循环。它们可以用于 Rust 语言提供的所有三种循环。

接下来是如何标记循环。

'标记: loop {}

要告诉编译器一个循环被标记了,从一个单引号字符开始,输入它的标签,然后跟着一个冒号。然后,继续使用你通常定义循环的方式。

当你需要退出某个循环时,只需像这样指定循环标签:

break '标记;

来看一个例子来更好地理解这个。

fn main() {
    let mut a = 0;
    let mut b = 0;

    'parent: loop {
        a += 1;

        loop {
            println!("a: {}, b: {}", a, b);
            b += 1;

            if a + b == 10 {
                println!("\n{} + {} = 10", a, b);
                break 'parent;
            }
        }
    }
}

这里,我使用两个可变变量 ab,它们的初始值都设置为 0。

然后,最外层的循环被标记为 parentparent 循环将变量 a 的值增加 1,并有一个内部/子循环。

这个(在第 8 行的)子循环打印变量 ab 的值。在这个循环内部,变量 b 的值增加了 1。退出条件是 a + b == 10。这意味着只要变量 ab 中存储的值相加,结果为 10,parent 循环就会被打破。即使第 14 行的 break 条件“属于”内部循环,它也会打破 parent 循环。

来看看程序的输出。

a: 1, b: 0
a: 1, b: 1
a: 1, b: 2
a: 1, b: 3
a: 1, b: 4
a: 1, b: 5
a: 1, b: 6
a: 1, b: 7
a: 1, b: 8

1 + 9 = 10

就像从程序输出中可以看出的那样,循环在 ab 分别具有值 1 和 9 时停止。

continue 关键字

如果你已经在其他编程语言(如 C/C++/Java/Python)中使用过循环,你可能已经知道 continue 关键字的用法。

break 关键字用于完全停止循环执行时,continue 关键字用于“跳过”循环执行的 当前迭代 并从下一迭代开始(如果条件允许)。

来看一个例子来理解 continue 关键字的工作原理。

fn main() {
    for i in 0..10 {
        if i % 2 == 0 {
            continue;
        }
        println!("{}", i)
    }
}

在上面的代码中,我有一个 for 循环,它迭代了 0 到 9 之间的整数(包括 0 和 9)。一旦循环开始,我就设置了一个条件检查,看看这个数字是不是偶数。如果这个数字是偶数,continue 关键字就会被执行。

但是如果这个数字是奇数,这个数字就会被打印到程序输出。

来看看这个程序的输出。

1
3
5
7
9

正如你所看到的,循环似乎一直在“进行”,尽管 0 到 9 之间显然有偶数。但是因为我使用了 continue 关键字,当遇到这个关键字时,循环执行就会停止。

这个循环跳过了它下面的任何东西,并继续下一次迭代。这就是为什么偶数没有被打印出来,但是 0 到 9 之间的所有奇数都被打印到了程序输出中。

总结

要总结这篇长文,我演示了 3 种不同循环的用法:forwhileloop。我还讨论了两个关键字,它们影响这些循环的控制流:breakcontinue

我希望你现在能理解每个循环的适当用例。如果你有任何问题,请告诉我。

(题图:MJ/25579e09-ae1c-47d3-8266-3bd9a54456c0)


via: https://itsfoss.com/rust-loops/

作者:Pratham Patel 选题:lkxed 译者:Cubik65536 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

相关内容

等了30年,微软MS-DO...
曾经称“开源是毒瘤”时有多么嫌弃,现在“微软 ❤️ 开源”就有多么...
2025-06-26 09:11:25
微软开源 Edit 命令行...
IT之家 5 月 20 日消息,微软昨日(5 月 19 日)发布博...
2025-05-20 08:16:36
做AI应用的最佳姿势:首选...
↓推荐关注↓ 最近我花了一些时间用 Tauri+SvelteKi...
2025-02-27 22:19:11
Rust 补丁两年零通过,...
整理|冬梅、明知山 策划|Tina 1Asahi Linux 首席...
2025-02-08 23:14:39
bypassSecurit...
问题描述:在Angular中使用bypassSecurityTru...
2025-01-12 20:02:27
不移动情况下将Rust的盒...
在Rust中,可以使用&符号来创建引用,这样可以在不移动变量的情况...
2025-01-11 06:00:23

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
2024 开年,LLUG 和你... Hi,Linuxer,2024 新年伊始,不知道你是否已经准备好迎接新的一年~ 2024 年,Lin...
什么是 KDE Connect... 什么是 KDE Connect?它的主要特性是什么?它应该如何安装?本文提供了基本的使用指南。科技日...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...