Rust入门笔记 4.流程控制

yyi
yyi
2023-08-13 / 0 评论 / 113 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年08月13日,已超过305天没有更新,若内容或图片失效,请留言反馈。

Rust 入门笔记 —— 流程控制

1. 分支

rust 的 if/else 和 go 的类似

  • 即使是单句也不能缺少大括号
  • 条件可以不用括号包裹
// Fill in the blanks
fn main() {
    let n = 5;

    if n < 0 {
        println!("{} is negative", n);
    } else if n > 0 {
        println!("{} is positive", n);
    } else {
        println!("{} is zero", n);
    }
} 

rust 的 if/else 结构可以用来赋值

// Fix the errors
fn main() {
    let n = 5;

    let big_n =
        if n < 10 && n > -10 {
            println!(", and is a small number, increase ten-fold");

            10 * n
        } else {
            println!(", and is a big number, halve the number");

            n / 2
        };

    println!("{} -> {}", n, big_n);
} 

2 循环

2.1 for

这个 for 和 py 的 for 比较类似,是一个 foreach 型的

fn main() {
    for n in 1..100 { // modify this line to make the code work
        if n == 100 {
            panic!("NEVER LET THIS RUN")
        }
    }

    println!("Success!");
} 

当遍历数组的时候,循环变量会获得被遍历的所有权(但是基本类型还是复制的)

    let names = [String::from("liming"),String::from("hanmeimei")];
    for name in names {
        // Do something with name...
    }

    println!("{:?}", names); // wrong!  borrow of moved value: `names`

所以我们可以用切片来遍历引用

  let names = [String::from("liming"),String::from("hanmeimei")];
    for name in &names {
        // Do something with name...
   }

    println!("{:?}", names);

通过数组的iter.enumrate方法,可以获得(index, value)的 tuple

fn main() {
    let a = [4, 3, 2, 1];

    // Iterate the indexing and value in 'a'
    for (i,v) in a.iter().enumerate() {
        println!("The {}th element is {}",i+1,v);
    }
}

2.2 while

while 循环和 C 的 while 是一样的,不过条件还是可以不加括号

// Fill in the blanks to make the last println! work !
fn main() {
    // A counter variable
    let mut n = 1;
    // Loop while the condition is true
    while n < 10 {
        if n % 15 == 0 {
            println!("fizzbuzz");
        } else if n % 3 == 0 {
            println!("fizz");
        } else if n % 5 == 0 {
            println!("buzz");
        } else {
            println!("{}", n);
        }
        n += 1;
    }
    println!("n reached {}, so loop is over",n);
}

Rust也有 continue 和 break 关键字

Rust 使用 loop 代替 while true

// Fill in the blanks
fn main() {
    let mut count = 0u32;
    println!("Let's count until infinity!");
    // Infinite loop
    loop {
        count += 1;
        if count == 3 {
            println!("three");
            // Skip the rest of this iteration
            continue;
      }
        println!("{}", count);
        if count == 5 {
            println!("OK, that's enough");
            break;
        }
    }
    assert_eq!(count, 5);
    println!("Success!");
}

loop是一个表达式,所以 break 可以用来返回值

// Fill in the blank
fn main() {
    let mut counter = 0;
    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2;
        }
    };
    assert_eq!(result, 20);
    println!("Success!");
}

通过 label 的方式,可以精确地 break 或 continue 嵌套循环

// Fill in the blank
fn main() {
    let mut count = 0;
    'outer: loop {
        'inner1: loop {
            if count >= 20 {
                // This would break only the inner1 loop
                break 'inner1; // `break` is also works.
            }
            count += 2;
        }
        count += 5;
        'inner2: loop {
            if count >= 30 {
                // This breaks the outer loop
                break 'outer;
            }
            // This will continue the outer loop
            continue 'outer;
        }
    }
    assert!(count == 30);
    println!("Success!");
}

3 模式匹配

3.1 match

match有点类似于 C 的 switch,其基本形式如下

match target {
  pattern1 => experssion1,
  pattern2 => {
    sth;
    expression
  },
  _ => expression
  
}

match需要穷举出所有的可能,用_代表所有未列出的可能(类似于 default)

match 的分支必须是表达式,且分支表达式的类型必须相同

pattern 可以用 X|Y的形式表示,代表 X 或 Y

// 填空
enum Direction {
    East,
    West,
    North,
    South,
}

fn main() {
    let dire = Direction::South;
    match dire {
        Direction::East => println!("East"),
        Direction::South|Direction::North  => { // 在这里匹配 South 或 North
            println!("South or North");
        },
        _ => println!("West"),
    };
}

match 本身也是一个表达式,因此可以用来赋值

fn main() {
    let boolean = true;

    // 使用 match 表达式填空,并满足以下条件
    //
    // boolean = true => binary = 1
    // boolean = false => binary = 0
    let binary = match boolean {
      true => 1,
      false => 0,
  };

    assert_eq!(binary, 1);
}

match可以取出模式中绑定的值,还记得我们的 enum 类型么

// 填空
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}
fn main() {
    let msgs = [
        Message::Quit,
        Message::Move{x:1, y:3},
        Message::ChangeColor(255,255,0)
    ];

    for msg in msgs {
        show_message(msg)
    }
} 

fn show_message(msg: Message) {
    match msg {
        Message::Move{x: a, y: b} => { // 这里匹配 Message::Move
            assert_eq!(a, 1);
            assert_eq!(b, 3);
        },
        Message::ChangeColor(_, g, b) => {
            assert_eq!(g, 255);
            assert_eq!(b, 0);
        }
        __ => println!("no data in these variants")
    }
}

3.2 if let

if let 对应于只有一个模式需要处理的情况,这时候用 match 需要写一个无用的 default

下面两份代码等价

fn main() {
    let o = Some(7);

    // 移除整个 `match` 语句块,使用 `if let` 替代
    match o {
        Some(i) => {
            println!("This is a really long string and `{:?}`", i);
        }
        _ => {}
    };
}
fn main() {
    let o = Some(7);
      if let Some(i) = o {
      println!("This is a really long string and `{:?}`", i);
  }
}

3.3 matches!

Rust提供了一个宏 matches,把表达式和模式进行匹配,返回是否匹配

let foo = 'f';
println!("{}", matches!(foo, 'A'..='Z' | 'a' ..= 'z')) // true
enum MyEnum {
    Foo,
    Bar
}

fn main() {
    let mut count = 0;

    let v = vec![MyEnum::Foo,MyEnum::Bar,MyEnum::Foo];
    for e in v {
        // if e == MyEnum::Foo { // 修复错误,只能修改本行代码
          if matches!(e, MyEnum::Foo) {
            count += 1;
        }
    }

    assert_eq!(count, 2);
}
0

评论 (0)

取消