rust笔记-流程控制

流程控制

一般情况,rust程序是一个顺序执行的程序,但是有些时候,我们需要根据不同的情况执行不同的代码,这时候就需要流程控制。

分支控制

if 条件判断,rust 中的 if 条件判断和 C 语言中的 if 条件判断基本一致,只是 rust 中的 if 条件判断可以省略大括号,同时 rust 中的 if 条件判断还可以省略小括号。

当然if 条件判断还可以使用 else 条件判断,当条件不满足时,执行 else 中的代码。还可以结合使用else 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");
    }
}

循环控制

rust中有三种循环控制:for循环、while循环、loop循环。

for循环

for循环可以遍历数组、字符串、集合等,也可以遍历数字,for循环的语法如下:

for i in <range> {
    // 循环体
}

其中, 可以是数组、字符串、集合等,也可以是数字。

使用for循环的时候一般需要使用集合的引用形式,否则所有权会被move到for循环中,导致在for语句外无法使用。对于实现了 copy 特征的数组(例如 [i32; 10] )而言, for item in arr 并不会把 arr 的所有权转移,而是直接对其进行了拷贝,因此循环之后仍然可以使用 arr 。

如果想在循环中,修改该元素,可以使用 mut 关键字:

for item in &mut collection {
  // ...
}

for循环使用方法是总结如下表:

使用方法 等价使用方法 所有权
for item in collection for item in IntoIterator::into_iter(collection) 所有权转移
for item in &collection for item in collection.iter() 不可变借用
for item in &mut collection for item in collection.iter_mut() 可变借用

如果要遍历数字,可以使用数字的 range 方法,语法如下,下面代码会打印1-9的数字:

fn main () {
    for i in 1..10 {
        println!("{}", i);
    }
}

如果想在循环中获取元素的索引,可以使用 enumerate 方法,语法如下:

fn main () {
    let a = [10, 20, 30, 40, 50];
    for (i, elem) in a.iter().enumerate() {
        println!("{}: the element is {}", i, elem);
    } 
}

如果不想声明一个变量来控制这个循环,可以使用_来替代i,_的意思是忽略这个值或者类型。下面代码会打印5次Hello, world!

fn main () {
    for _ in 0..5 {
        println!("Hello, world!");
    }
}

两种for循环的对比:

// 第一种
let collection = [1, 2, 3, 4, 5];
for i in 0..collection.len() {
  let item = collection[i];
  // ...
}

// 第二种
for item in collection {

}

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

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

continue 和 break 关键字

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

for i in 1..4 {
if i == 2 {
continue;
}
println!("{}", i);
}
上面代码对 1 到 3 的序列进行迭代,且跳过值为 2 时的循环

使用 break 可以跳出整个循环,结束循环:

for i in 1..4 {
if i == 2 {
break;
}
println!("{}", i);
}
上面代码对 1 到 3 的序列进行迭代,在遇到值为 2 时的跳出整个循环,后面的循环不再执行。

while 循环

while 循环和 for 循环类似,区别在于 while 循环可以事先不知道循环次数,需要一个循环条件,当条件为真时,循环继续,条件为假时,循环结束。使用方法如下:

fn main () {
    let mut number = 3;
    while number != 0 {
        println!("{}", number);
        number = number - 1;
    }
}

当然也可以使用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;
    }
}

但是这种实现如果索引长度不正确,容易导致程序崩溃,还有在每次执行都需要进行条件检查,从而影响性能。所以对于明确需要遍历的场景,更推荐使用for循环。

loop循环

loop 就是一个简单的无限循环,可以在内部实现逻辑通过 break 关键字来控制循环何时结束。与 while 循环不同的是,loop 循环没有循环条件,因此需要使用 break 关键字来控制循环何时结束。所以使用的时候要谨慎,避免无限循环。我们来看一个使用loop循环的例子:

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;

        if counter == 10 {
            break counter * 2;
        }
    };

    println!("The result is {}", result);
}

上面代码中,loop 循环中,counter 从 0 开始不断自增 1,直到 counter 等于 10 时,使用 break 关键字退出循环,并返回值 counter * 2。break可以单独使用直接退出循环,退出循环的同时返回一个值。

tip:loop 循环没有循环条件,因此需要使用 break 关键字来控制循环何时结束。loop是个表达式,可以返回一个值。

posted @   NoodlesYang  阅读(8)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示