• Rust 流程控制和循环控制


    Rust 流程控制

    IF

    if else 表达式根据条件执行不同的代码分支:

    fn main() {
        let condition = true;
        let number = if condition {
            5
        } else {
            6
        };
    
        println!("The value of number is: {}", number);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • if 语句是表达式, 使用 if 表达式的返回值来给 number 进行赋值。
    • 用 if 来赋值时,要保证每个分支返回的类型一样。

    else if 处理多重条件

    fn main() {
        let n = 6;
    
        if n % 4 == 0 {
            println!("number is divisible by 4");
        } else if n % 3 == 0 {
            println!("number is divisible by 3");
        } else if n % 2 == 0 {
            println!("number is divisible by 2");
        } else {
            println!("number is not divisible by 4, 3, or 2");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    从上至下检查每一个分支判断,一旦成功,则跳出 if 语句块。

    循环控制

    有三种循环方式,for,while,loop。

    for 循环

    fn main() {
        for i in 1..=5 {
            println!("{}", i);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    循环输出从 1 到 5 的序列。

    1…=5 是 1到5,1…5 是 1到4
    for 元素 in 集合

    同样需要考虑集合的所有权问题,如果集合是非 copy 特性的数组时 (如 [i32; 5] 是 copy 特性的数组),后续则不能继续使用该集合。

    当然,可以使用引用避免上面的情况

    for item in &container {
      //...
    }
    
    • 1
    • 2
    • 3

    如果想在循环中,修改该元素,则需要给集合 mut 关键字

    for item in &mut container {
      //...
    }
    
    • 1
    • 2
    • 3

    如果想在循环时获取索引

    fn main() {
        let a = [4, 3, 2, 1];
        // `.iter()` 方法把 `a` 数组变成一个迭代器
        for (i, v) in a.iter().enumerate() {
            println!("第{}个元素是{}", i + 1, v);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    不想使单独声明一个变量来控制流程。_ 忽略该值或者类型。

    for _ in 0..10 {
      //..
    }
    
    • 1
    • 2
    • 3

    两种方式比较

    // 第一种
    let collection = [1, 2, 3, 4, 5];
    for i in 0..collection.len() {
      let item = collection[i];
      // ...
    }
    
    // 第二种
    for item in collection {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    第一种方式是循环索引,然后通过索引下标去访问集合,第二种方式是直接循环集合中的元素,优劣如下:

    • 性能:第一种使用方式中 collection[index] 的索引访问,会因为边界检查(Bounds Checking)导致运行时的性能损耗 —— Rust 会检查并确认 index 是否落在集合内,但是第二种直接迭代的方式就不会触发这种检查,因为编译器会在编译时就完成分析并证明这种访问是合法的
    • 安全:第一种方式里对 collection 的索引访问是非连续的,存在一定可能性在两次访问之间,collection 发生了变化,导致脏数据产生。而第二种直接迭代的方式是连续访问,因此不存在这种风险

    由于 for 循环无需任何条件限制,也不需要通过索引来访问,因此是最安全也是最常用的。

    containue

    使用 continue 可以跳过当前当次的循环,开始下次的循环:

     for i in 1..4 {
         if i == 2 {
             continue;
         }
         println!("{}", i);
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    会跳过值为 2 时的循环。

    break

    使用 break 可以直接跳出当前整个循环:

     for i in 1..4 {
         if i == 2 {
             break;
         }
         println!("{}", i);
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在等于 2 时跳出整个循环。

    While 循环

    如果你需要一个条件来循环,当该条件为 true 时,继续循环,条件为 false,跳出循环,那么 while 就非常适用:

    fn main() {
        let mut n = 0;
    
        while n <= 5  {
            println!("{}!", n);
    
            n = n + 1;
        }
    
        println!("我出来了!");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    当 大于 5 时就退出了。

    也可以使用 loop + if + break 来实现:

    fn main() {
        let mut n = 0;
    
        loop {
            if n > 5 {
                break
            }
            println!("{}", n);
            n+=1;
        }
    
        println!("我出来了!");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    相比较,while 较为简练。

    while vs for
    我们也能用 while 来实现 for 的功能:

    fn main() {
        let a = [10, 20, 30, 40, 50];
        let mut index = 0;
    
        while index < 5 {
            println!("the value is: {}", a[index]);
    
            index = index + 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    代码对数组中的元素进行计数。它从索引 0 开始,并接着循环直到遇到数组的最后一个索引(这时,index < 5 不再为真)。
    如果索引长度不正确会导致程序 panic,所以编译器增加了运行时代码来对每次循环的元素进行条件检查。

    for 循环

    fn main() {
        let a = [10, 20, 30, 40, 50];
    
        for element in a.iter() {
            println!("the value is: {}", element);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可以看出,for 并不会使用索引去访问数组,因此更安全也更简洁,同时避免 运行时的边界检查,性能更高。

    Loop 循环

    对于循环而言,loop 循环毋庸置疑,是适用面最高的,它可以适用于所有循环场景(虽然能用,但是在很多场景下, for 和 while 才是最优选择),因为 loop 就是一个简单的无限循环,你可以在内部实现逻辑通过 break 关键字来控制循环何时结束。

    当使用 loop 时,必不可少的伙伴是 break 关键字,它能让循环在满足某个条件时跳出:

    fn main() {
        let mut counter = 0;
    
        let result = loop {
            counter += 1;
    
            if counter == 10 {
                break counter * 2;
            }
        };
    
        println!("The result is {}", result);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    以上代码当 counter 递增到 10 时,就会通过 break 返回一个 counter * 2 的值,最后赋给 result 并打印出来。

    这里有几点值得注意:

    • break 可以单独使用,也可以带一个返回值,有些类似 return
    • loop 是一个表达式,因此可以返回一个值。
  • 相关阅读:
    【PACS系统源码】与医院HIS系统双向数据交换,实现医学影像集成与影像后处理功能
    Proteus8.10软件安装教程
    聊聊心理医疗领域大模型的落地思考
    WinFrom应用程序开机自启动
    (附源码)spring boot信佳玩具有限公司仓库管理系统 毕业设计 011553
    18 矩阵置0
    单片机学习笔记之点亮led 灯
    【JavaSE】阶段性小结,运用Java实现图书管理系统
    聊聊并发编程——原子操作类和Fork/Join框架
    单商户商城系统功能拆解40—分销应用—分销设置
  • 原文地址:https://blog.csdn.net/mr1jie/article/details/125418774