Rust的控制流:条件、循环以及模式匹配

条件控制

Rust的条件控制也是使用if else,和其他语言相比没有多大区别,直接看例子:

fn main() 
{
    let number = 10;

    if  number < 0
    {
        println!("number小于0");
    }
    else if 0 <= number && number <= 5
    {
        println!("number在0~5之间");
    } 
    else if number > 5 && number <= 10
    {
        println!("number在5~10之间");
    }
    else
    {
        println!("number大于10");
    }
}

一定要牢记Rust是基于表达式的语言,除了声明语句和表达式语句外,其他的都是表达式。所以if也是表达式,它可以被用作右值。如:

fn main() 
{
    let number = 10;
    let condition = if  number < 0
    {
        1
    }
    else if 0 <= number && number <= 10    
    {
        2
    }
    else
    {
        3
    };

    println!("condition is {}", condition);
}

循环控制

Rust提供了三种循环方式:

  • for
  • while
  • loop

for

Rust的for很像Python,可以遍历一个迭代器,如:

for x in 0..10 
{ 
    println!("{}", x); 
}

Rust的类型大都内置了迭代器,可以直接进行遍历。如:

fn main() 
{
    // 遍历数组
    let a = [1,2,3,4,5];
    for x in a.iter()
    { 
        println!("{}", x); 
    }

    // 遍历切片
    for x in a[..].iter()
    { 
        println!("{}", x); 
    }

    // 遍历字符串
    let b = "hello";
    for x in b.chars()
    { 
        println!("{}", x); 
    }

    // 遍历动态数组
    let c = vec![1,2,3,4,5];
    for x in c.iter()
    { 
        println!("{}", x); 
    }
}

需要注意的是,使用迭代器遍历,得到的不是值本身,而是对值的引用,如:

fn main() 
{
    let a = [1, 2, 3, 4, 5, 6, 7, 8];
    for v in a.iter()
    {
        if v == 3
        {
            println!("found");
        }
    }
}

编译会报错:

error[E0277]: can't compare `&{integer}` with `{integer}`
 --> src\main.rs:6:14
  |
6 |         if v == 3
  |              ^^ no implementation for `&{integer} == {integer}`
  |
  = help: the trait `std::cmp::PartialEq<{integer}>` is not implemented for `&{integer}`

error: aborting due to previous error

此时,需要在v前面加*,类似于C/C++的指针:

fn main() 
{
    let a = [1, 2, 3, 4, 5, 6, 7, 8];
    for *v in a.iter()
    {
        if v == 3
        {
            println!("found");
        }
    }
}

像Python那样,Rust也提供了enumerate函数,来记录循环的次数:

fn main() 
{
    // 遍历数组
    let a = [1,2,3,4,5];
    for (i, x) in a.iter().enumerate()  // enumerate是迭代器的函数
    { 
        println!("{}:{}", i, x); 
    }
}

while

Rust的while循环和大多数语言那样,没有什么特殊性:

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

loop

Rust比其他语言多了一个loop循环,loop就相当于while true,它没有结束的条件,只要没有break就一直循环下去。当然,这不仅仅是写法上的不同,编译器会对loop循环做更多的优化,来保证循环执行的效率和安全性更高。

fn main() 
{
    let mut number = 10;
    loop
    {
        println!("{}", number);
        number -= 1;
        if number == 0
        {
            break;
        }
    }
}

break/continue

令人兴奋的是,Rust赋予break/continue强大的功能。使循环控制变得更加有趣。

  1. 跳出到指定的标签
    Rust可以为循环指定标签,有多层循环嵌套时,可以直接指定跳出哪个循环:
    fn main() 
    {
        let (mut i, mut j) = (0, 0);
        'outer: loop
        {
            'inner: loop
            {
                j += 1;
                println!("i={}, j={}", i, j);
    
                if j == 10
                {
                    break 'outer;       // 跳出外层循环
                }
            }
    
            i += 1;
        }
    }
    
    fn main() 
    {
        let (mut i, mut j) = (0, 0);
        'outer: loop
        {
            i += 1;
            j = 0;
            'inner: loop
            {
                j += 1;
                println!("i={}, j={}", i, j);
    
                if j == 10
                {
                    continue 'outer;       // 继续外层循环
                }
            }
        }
    }
    
  2. 作为右值
    还是那句话,Rust是基于表达式的语言,这赋予了Rust很多新的特性。像前面提到的if是表达式一样,loop和break都是表达式,同样可以作为右值:
    fn main() 
    {
        let a = [1, 2, 3, 4, 5, 6, 7, 8];
        let mut index:usize = 0;
        
        // 从数组a中查找是否有0
        let found = loop
        {
            if a[index] == 0
            {
                break true
            }
    
            if index == a.len() - 1
            {
                break false
            }
    
            index += 1;
        };
    
        println!("found = {}", found);
    }
    

模式匹配

C/C++中有switch,可以控制多个流程分支。Rust把switch进行了升级,提供了match关键字,这是一个非常强大的控制流运算符,被称为模式匹配。
假如我们有一堆硬币,面值1元、0.5元0.1元,分别统计硬币的个数:

fn main() 
{
    let corns = [1.0, 0.5, 0.5, 1.0, 0.1, 1.0, 1.0, 0.5, 0.5, 1.0, 1.0, 1.0, 0.1];

    let (mut c1, mut c2, mut c3) = (0, 0, 0);

    for v in corns.iter()
    {
        match *v
        {
            1.0 => c1 += 1,
            0.5 => c2 += 1,
            0.1 => c3 += 1,
            _ => break
        }
    }

    println!("有1元硬币{}个, 5角硬币{}个,1角硬币{}个。", c1, c2, c3);
}

这种用法与C/C++中switch的用法类似,只是每个分支不需要加break。
在Rust中,match后面跟一个表达式,然后是分支。每个分支又分成两个部分,=>前面的部分叫模式,=>后面是执行体。
match执行时,先计算表达式的值,然后用该值与模式逐一进行匹配,当匹配成功时,执行该模式对应的执行体。若多个模式都匹配,也只执行第一个匹配成功的执行体。模式必须能覆盖所有的可能性,可以使用“_”,匹配其他的情况,类似于C/C++的default。
Rust的模式匹配功能非常强大,我试图跳过一些内容去理解模式匹配,但是确实有很多地方看不明白,需要等到学习到一定阶段才能去学习。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值