MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Rust控制流与循环

2022-02-265.5k 阅读

Rust 控制流概述

在 Rust 编程中,控制流语句是构建复杂程序逻辑的基础。它们允许我们根据条件执行不同的代码块,或者重复执行特定的代码片段。Rust 提供了几种主要的控制流结构,包括 if - else 语句、match 表达式以及各种循环结构,如 loopwhilefor。这些控制流工具让开发者能够灵活地控制程序的执行流程,以实现各种功能。

if - else 语句

if - else 语句是最基本的条件控制结构。它允许根据一个布尔表达式的值来决定执行哪一部分代码。语法如下:

fn main() {
    let number = 5;
    if number > 3 {
        println!("The number is greater than 3");
    } else {
        println!("The number is less than or equal to 3");
    }
}

在上述代码中,首先定义了一个变量 number 并赋值为 5。然后,if 条件判断 number 是否大于 3。如果条件为真,就执行 if 代码块中的 println! 语句;否则,执行 else 代码块中的语句。

if 语句中的条件必须是一个布尔值。如果我们使用非布尔值,Rust 编译器会报错。例如:

fn main() {
    let number = 5;
    // 错误:条件必须是布尔值
    if number {
        println!("This won't compile");
    }
}

这段代码会导致编译错误,因为 number 是一个整数,而不是布尔值。

多分支 if - else if - else

当需要根据多个条件进行不同处理时,可以使用 if - else if - else 结构。例如:

fn main() {
    let number = 7;
    if number < 5 {
        println!("The number is less than 5");
    } else if number < 10 {
        println!("The number is between 5 (inclusive) and 10");
    } else {
        println!("The number is 10 or greater");
    }
}

在这个例子中,首先检查 number 是否小于 5。如果不满足,接着检查是否小于 10。如果前两个条件都不满足,就执行 else 代码块。

if 作为表达式

在 Rust 中,if 语句不仅仅是一个控制结构,它还是一个表达式,这意味着它有一个返回值。例如:

fn main() {
    let condition = true;
    let number = if condition { 5 } else { 10 };
    println!("The value of number is: {}", number);
}

在这段代码中,if 表达式根据 condition 的值返回 510,并将返回值赋给变量 numberif 表达式的两个分支(ifelse)必须返回相同类型的值,否则会导致编译错误。

match 表达式

match 表达式是 Rust 中强大的模式匹配工具,它可以根据一个值的不同可能性执行不同的代码。match 表达式由一个需要匹配的值和一系列分支组成,每个分支包含一个模式和对应的代码块。语法如下:

fn main() {
    let number = 3;
    match number {
        1 => println!("One"),
        2 => println!("Two"),
        3 => println!("Three"),
        _ => println!("Something else"),
    }
}

在这个例子中,match 表达式对 number 的值进行匹配。如果 number 等于 1,就执行 1 => println!("One") 这一分支;如果等于 2,执行 2 => println!("Two") 分支;如果等于 3,执行 3 => println!("Three") 分支;如果都不匹配,执行 _ => println!("Something else") 分支。这里的 _ 是一个通配符模式,匹配所有其他值。

匹配复杂类型

match 表达式不仅可以匹配简单的数值类型,还可以匹配复杂类型,如枚举和结构体。以枚举为例:

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}
fn main() {
    let my_coin = Coin::Dime;
    let value = value_in_cents(my_coin);
    println!("The value of the coin is {} cents", value);
}

在上述代码中,定义了一个 Coin 枚举,然后在 value_in_cents 函数中使用 match 表达式根据不同的 Coin 变体返回相应的分值。

绑定值的模式

match 表达式中的模式可以绑定值。例如:

fn main() {
    let (x, y) = (10, 20);
    match (x, y) {
        (a, b) if a < b => println!("The first value {} is less than the second value {}", a, b),
        (a, b) if a > b => println!("The first value {} is greater than the second value {}", a, b),
        _ => println!("The values are equal or some other case"),
    }
}

这里 (a, b) 模式将 (x, y) 元组中的值分别绑定到 ab,然后通过 if 条件进一步判断并执行相应的代码块。

循环结构

Rust 提供了三种主要的循环结构:loopwhilefor。每种循环结构适用于不同的场景,开发者可以根据具体需求选择合适的循环。

loop 循环

loop 循环用于无限循环执行代码块,直到显式地使用 break 语句退出循环。语法如下:

fn main() {
    let mut counter = 0;
    loop {
        counter += 1;
        if counter == 3 {
            println!("Reached 3, breaking out of the loop");
            break;
        }
        println!("Counter: {}", counter);
    }
}

在这个例子中,loop 循环不断增加 counter 的值。当 counter 等于 3 时,执行 break 语句,退出循环。

loop 循环返回值

loop 循环可以通过 break 语句返回一个值。例如:

fn main() {
    let result = loop {
        let number = 5;
        if number > 3 {
            break number * 2;
        }
    };
    println!("The result is: {}", result);
}

在这段代码中,loop 循环检查 number 是否大于 3。如果满足条件,break 语句返回 number * 2 的值,并将其赋给 result 变量。

while 循环

while 循环根据一个布尔条件来决定是否继续执行循环体。只要条件为真,循环就会持续执行。语法如下:

fn main() {
    let mut number = 3;
    while number > 0 {
        println!("Number: {}", number);
        number -= 1;
    }
    println!("Loop ended, number is now: {}", number);
}

在这个例子中,while 循环检查 number 是否大于 0。只要条件满足,就打印 number 的值并将其减 1。当 number 变为 0 时,条件为假,循环结束。

使用 while 模拟 for 循环

虽然 Rust 有专门的 for 循环用于遍历集合,但有时可以使用 while 循环来模拟类似的行为。例如:

fn main() {
    let numbers = [10, 20, 30];
    let mut index = 0;
    while index < numbers.len() {
        println!("Number at index {} is: {}", index, numbers[index]);
        index += 1;
    }
}

这里通过 while 循环和索引变量 index 来遍历数组 numbers

for 循环

for 循环是 Rust 中最常用的用于遍历集合(如数组、向量、字符串等)的循环结构。语法如下:

fn main() {
    let numbers = [10, 20, 30];
    for number in numbers {
        println!("Number: {}", number);
    }
}

在这个例子中,for 循环依次将 numbers 数组中的每个元素赋值给 number 变量,并执行循环体中的 println! 语句。

使用 for 循环和 range

for 循环常与 range 结合使用,以迭代一系列数字。例如:

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

这里 1..5 表示一个左闭右开的范围,即从 14for 循环会依次将 1234 赋值给 i 并执行循环体。

如果需要一个闭区间,可以使用 1..=5,这样范围就包括 15

遍历集合的索引和值

有时我们不仅需要集合中的值,还需要其索引。可以使用 enumerate 方法来实现:

fn main() {
    let fruits = ["apple", "banana", "cherry"];
    for (index, fruit) in fruits.iter().enumerate() {
        println!("Index {}: {}", index, fruit);
    }
}

在这个例子中,iter() 方法将数组转换为迭代器,enumerate() 方法为迭代器中的每个元素添加一个索引,从而可以同时获取索引和值。

循环控制语句

在循环中,我们可以使用一些控制语句来改变循环的执行流程,主要包括 breakcontinue

break 语句

break 语句用于立即终止当前循环,跳出循环体。我们在前面的 loopwhile 循环示例中已经看到了 break 的使用。在嵌套循环中,break 语句默认终止最内层的循环。例如:

fn main() {
    for i in 1..4 {
        for j in 1..4 {
            if i * j > 5 {
                break;
            }
            println!("{} * {} = {}", i, j, i * j);
        }
    }
}

在这个嵌套循环中,当 i * j 大于 5 时,内层循环使用 break 语句终止,程序继续执行外层循环的下一次迭代。

如果要终止外层循环,可以给外层循环命名,并在 break 语句中指定这个名称。例如:

fn main() {
    'outer_loop: for i in 1..4 {
        for j in 1..4 {
            if i * j > 5 {
                break 'outer_loop;
            }
            println!("{} * {} = {}", i, j, i * j);
        }
    }
}

这里给外层循环命名为 outer_loop,当 i * j 大于 5 时,break 'outer_loop 语句会终止外层循环。

continue 语句

continue 语句用于跳过当前循环迭代中剩余的代码,直接进入下一次迭代。例如:

fn main() {
    for i in 1..6 {
        if i == 3 {
            continue;
        }
        println!("Number: {}", i);
    }
}

在这个 for 循环中,当 i 等于 3 时,continue 语句会跳过 println! 语句,直接进入下一次迭代,因此不会打印 3

总结

Rust 的控制流和循环结构为开发者提供了丰富的工具来构建复杂的程序逻辑。if - else 语句用于基本的条件判断,match 表达式提供了强大的模式匹配功能,而 loopwhilefor 循环适用于不同类型的迭代需求。同时,breakcontinue 等控制语句可以灵活地改变循环的执行流程。熟练掌握这些控制流和循环结构,对于编写高效、可读的 Rust 代码至关重要。无论是开发小型脚本还是大型应用程序,这些基础知识都是不可或缺的。在实际编程中,根据具体的问题场景选择合适的控制流和循环结构,可以使代码更加简洁、清晰,并且易于维护。通过不断地实践和运用这些知识,开发者能够充分发挥 Rust 语言的优势,编写出高质量的软件。