let number = 6; if number < 5 { println!("条件为真"); } else { println!("条件为假"); }
let number = 6; if number % 4 == 0 { println!("能被4整除"); } else if number % 3 == 0 { println!("能被3整除"); } else if number % 2 == 0 { println!("能被2整除"); } else { println!("不能被4、3或2整除"); }
Rust的if是一个表达式,可以返回值:
let condition = true; let number = if condition { 5 } else { 6 }; println!("number的值是:{}", number); // 5
重要规则:if分支返回的类型必须相同。
// 错误示例 let number = if condition { 5 } else { "six" }; // 编译错误!
Rust有三种循环:loop、while和for。
loop { println!("永远循环!"); // 使用break退出 }
带返回值的loop:
let mut counter = 0; let result = loop { counter += 1; if counter == 10 { break counter * 2; // 返回值 } }; println!("结果:{}", result); // 20
loop标签:
let mut count = 0; 'counting_up: loop { println!("count = {}", count); let mut remaining = 10; loop { println!("remaining = {}", remaining); if remaining == 9 { break; // 退出内层循环 } if count == 2 { break 'counting_up; // 退出外层循环 } remaining -= 1; } count += 1; } println!("结束 count = {}", count);
let mut number = 3; while number != 0 { println!("{}!", number); number -= 1; } println!("发射!");
用while遍历数组:
let a = [10, 20, 30, 40, 50]; let mut index = 0; while index < 5 { println!("值为:{}", a[index]); index += 1; }
遍历集合:
let a = [10, 20, 30, 40, 50]; for element in a.iter() { println!("值为:{}", element); }
使用Range:
// 1到3(不包括4) for number in 1..4 { println!("{}!", number); } // 1到4(包括4) for number in 1..=4 { println!("{}!", number); } // 反向 for number in (1..4).rev() { println!("{}!", number); }
带索引的遍历:
let v = vec!['a', 'b', 'c']; for (index, value) in v.iter().enumerate() { println!("{} 在索引 {}", value, index); }
match是Rust强大的模式匹配结构,类似C的switch但功能更强大。
let number = 7; match number { 1 => println!("一"), 2 => println!("二"), 3 => println!("三"), 4 => println!("四"), 5 => println!("五"), _ => println!("其他"), }
match必须穷尽(exhaustive):
let number = 7; match number { 1 => println!("一"), // 错误!缺少其他情况的处理 }
let number = 1; match number { 1 | 2 => println!("一或二"), 3..=7 => println!("三到七之间"), _ => println!("其他"), }
let number = 2; let result = match number { 1 => "一", 2 => "二", 3 => "三", _ => "其他", }; println!("结果是:{}", result);
let point = (3, 5); match point { (0, 0) => println!("原点"), (x, 0) => println!("x轴上,x = {}", x), (0, y) => println!("y轴上,y = {}", y), (x, y) => println!("点 ({}, {})", x, y), }
struct Point { x: i32, y: i32, } let p = Point { x: 0, y: 7 }; match p { Point { x, y: 0 } => println!("在x轴上,x = {}", x), Point { x: 0, y } => println!("在y轴上,y = {}", y), Point { x, y } => println!("点 ({}, {})", x, y), }
使用..忽略剩余字段:
struct Point3D { x: i32, y: i32, z: i32, } let p = Point3D { x: 1, y: 2, z: 3 }; match p { Point3D { x, .. } => println!("x是{}", x), }
enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } let msg = Message::ChangeColor(0, 160, 255); match msg { Message::Quit => { println!("Quit"); } Message::Move { x, y } => { println!("移动到 x: {}, y: {}", x, y); } Message::Write(text) => { println!("文本消息:{}", text); } Message::ChangeColor(r, g, b) => { println!("改变颜色为 R: {}, G: {}, B: {}", r, g, b); } }
对于只关心一个模式的情况:
let some_value = Some(3); // match写法 match some_value { Some(3) => println!("是三"), _ => (), } // if let写法(更简洁) if let Some(3) = some_value { println!("是三"); }
if let带else:
if let Some(3) = some_value { println!("是三"); } else { println!("不是三"); }
let mut stack = Vec::new(); stack.push(1); stack.push(2); stack.push(3); while let Some(top) = stack.pop() { println!("弹出:{}", top); }
@运算符允许在测试模式的同时创建变量:
enum Message { Hello { id: i32 }, } let msg = Message::Hello { id: 5 }; match msg { Message::Hello { id: id_variable @ 3..=7 } => { println!("id在范围内:{}", id_variable); } Message::Hello { id: 10..=12 } => { println!("id在10到12之间,但没有绑定"); } Message::Hello { id } => { println!("其他id:{}", id); } }
let num = Some(4); match num { Some(x) if x < 5 => println!("小于5:{}", x), Some(x) => println!("{}", x), None => (), }
多个模式的守卫:
let x = 4; let y = false; match x { 4 | 5 | 6 if y => println!("yes"), _ => println!("no"), }
使用_忽略整个值:
fn foo(_: i32, y: i32) { println!("y = {}", y); } foo(3, 4);
使用_忽略部分值:
let mut setting_value = Some(5); let new_setting_value = Some(10); match (setting_value, new_setting_value) { (Some(_), Some(_)) => { println!("不能覆盖已有值"); } _ => { setting_value = new_setting_value; } }
使用以_开头的名称:
let s = Some(String::from("Hello!")); if let Some(_s) = s { println!("找到了字符串"); } // println!("{:?}", s); // 错误!s已被移动
使用_则不会移动:
if let Some(_) = s { println!("找到了字符串"); } println!("{:?}", s); // 正确!
use std::io; fn main() { let secret_number = 42; loop { println!("请输入你的猜测:"); let mut guess = String::new(); io::stdin() .read_line(&mut guess) .expect("读取失败"); let guess: i32 = match guess.trim().parse() { Ok(num) => num, Err(_) => { println!("请输入数字!"); continue; } }; match guess.cmp(&secret_number) { std::cmp::Ordering::Less => println!("太小了!"), std::cmp::Ordering::Greater => println!("太大了!"), std::cmp::Ordering::Equal => { println!("猜对了!"); break; } } } }
fn main() { for n in 1..=100 { match (n % 3, n % 5) { (0, 0) => println!("FizzBuzz"), (0, _) => println!("Fizz"), (_, 0) => println!("Buzz"), _ => println!("{}", n), } } }
fn calculate(a: f64, b: f64, op: char) -> Option<f64> { match op { '+' => Some(a + b), '-' => Some(a - b), '*' => Some(a * b), '/' => if b != 0.0 { Some(a / b) } else { None }, _ => None, } } fn main() { let a = 10.0; let b = 3.0; let op = '*'; match calculate(a, b, op) { Some(result) => println!("{} {} {} = {}", a, op, b, result), None => println!("无效操作或除零错误"), } }
fn number_to_chinese(n: u32) -> String { match n { 0 => "零".to_string(), 1 => "一".to_string(), 2 => "二".to_string(), 3 => "三".to_string(), 4 => "四".to_string(), 5 => "五".to_string(), 6 => "六".to_string(), 7 => "七".to_string(), 8 => "八".to_string(), 9 => "九".to_string(), 10 => "十".to_string(), _ => n.to_string(), } } fn main() { for i in 0..=10 { println!("{} -> {}", i, number_to_chinese(i)); } }
本章学习了Rust的控制流结构:
控制流是编程的基础,Rust的模式匹配系统特别强大,建议多加练习。