Skip to content

控制流

根据条件是否为true来决定是否执行某段代码,或者循环执行某段代码。Rust中常见的控制流有:if表达式、循环、模式匹配(match)。

if 表达式

1. if 表达式的特征

  • if 表达式当条件为true时就执行表达式内的代码,否则就不执行。
  • if 表达式可选地组合else,顺序地执行后续的代码。
  • if 表达式的判断条件必须为 bool 类型(返回 bool 类型的函数等),因为rust不会隐式地转换数据地类型。
  • if、else if可用于多重条件判;需要注意的是,Rust 只会执行第一个条件为真的代码块。当某一个分支的条件满足后,即使后续分支的条件也满足,也不会再执行其它代码块了。
rust
fn main(){
    
    //判断条件必须为bool类型
    if 6 > 0 {
        println!("{}",true)
    }
    if is_alter(6) {
        println!("{}",true)
    }
    else {
        println!("{}",false)
    }

    
	//多重判断,第一个分支满足条件了,所以只会输出“fisrt arm”,后续的分支不会再执行了
    if is_alter(10) {
        println!("fisrt arm")
    }else if is_alter(6) {
        println!("second arm")
    }else {
        println!("no match arm")
    }
}
pub fn is_alter(num:i32) -> bool{
    num > 5
}

2. 在 let 语句中使用 if

  • if 是一个表达式,所以可以在 let 语句的右侧使用它来将结果赋值给一个变量。
  • if...else的每个分支的可能的返回值都必须是相同类型,因为rust在 编译时期就要准确地知道每个变量地类型,就可以在编译时验证在每处使用的 number 变量的类型是有效的。
rust
fn main(){
    let condition:bool = true;

    //if的每个分支都必须返回相同的类型
    let number = if condition { 5 } else { 4 };
    println!("number is {}",number);

    //返回不同的类型时,会触发panic:expected integer, found `&str`
    // let x = if condition { 5 } else { "SIX" };
    // println!("number is {}",x);
}

循环

循环是指遍历执行循环体中的代码直至结尾,然后再回到开头重新执行。Rust提供了多种循环:loopwhilefor等。

1. loop循环

无限循环执行表达式里的代码块,直至你要求停止。

rust
fn main(){
    loop{
		println!("hello,world");
	}
}

上面的代码会不断地在控制台打印hello,world,直到我使用 Ctrl + C来终止程序。

2. while条件循环

条件为真,执行循环。当条件不再为真,调用 break 停止循环。

rust
fn mian(){
	let mut x = 3;
    while x != 0{
        println!("x is {}",x);
        x -= 1;
    }
    println!("hello,world")
}

上面的while循环会执行三次,这时x变成0,条件判断为false,调用break终止循环,然后打印hello,world结束程序。

3. for 循环遍历集合

使用while循环也可以遍历合集的元素,通过将判断条件设定问集合索引的边界实现循环访问。

rust
fn main(){
    let x = [1,2,3,4,5];
    let mut index = 0;
    while index < 5{
        println!("第{}个元素是:{}",index,x[index])
    }
}
shell
第0个元素是:1
第1个元素是:2
第2个元素是:3
第3个元素是:4
第4个元素是:5

index 在某一时刻会到达值 5,不过循环在其尝试从数组获取第 6 个值:x[5](会越界)之前就停止了。如果索引值或测试条件不正确会导致程序 panic,

这使程序更慢,因为编译器增加了运行时代码来对每次循环进行条件检查,以确定在循环的每次迭代中索引是否在数组的边界内。

更简洁的替代方案是for循环:

rust
fn main(){
    for i in x {
        println!("第{}个元素是:{}",i,i);
    }
}
shell
第1个元素是:1
第2个元素是:2
第3个元素是:3
第4个元素是:4
第5个元素是:5

与while遍历集合不同的是,for循环直接遍历集合的元素,而不是借助索引,这很好地避免了集合的边界问题。

4. 循环标签、continue、break

  • 使用'labelName:标识loop,这个名字就叫做 “循环标签” 。
  • break 关键字来告诉程序何时停止循环。
  • continue 关键字告诉程序跳过当前迭代中的任何剩余代码,并转到下一个迭代。
rust
fn main(){
    let mut x = 0;
    'outer:loop{
        println!("x is {}",x);
        let mut z = 10;
        'inner:loop{
            println!("z is {}",z);
            if z == 9 {
                break 'inner ;
            }
            if x == 2 {
                break 'outer;
            }
            z -= 1;
        }
        x += 1;
    }
}

上述代码为双层嵌套的loop循环,执行流程如下:

  1. inner loop执行一次使 z = 9 后,满足第一个 if 条件,被break跳出。回到outer loop继续执行后续代码,x变为1,进入outer loop的下一次迭代,z被重新声明为10。
  2. 进入inner loop,重复执行步骤一,差异是,这时x变为2,然后进入outer loop的下一个迭代,最终进入inner loop,这时第二个 if 条件被满足,跳出``outer loop`,至此程序结束。
shell
x is 0
z is 10
z is 9
x is 1
z is 10
z is 9
x is 2
z is 10
rust
fn main() {
    let mut count = 0;
    while count < 10 {
        count += 1;
        if count % 2 == 0{
            continue;
        }
        println!("count is {}",count)
    }
}

上述代码中当 count 整除2时,就使用continue跳出当前迭代,因此当前迭代后续的 println 代码就不会执行了。

shell
count is 1
count is 3
count is 5
count is 7
count is 9

模式匹配

模式匹配需要用到枚举相关知识,后续再讨论。