脚本之家

电脑版
提示:原网页已由神马搜索转码, 内容由www.jb51.net提供.
您的位置:首页软件编程Rust语言→ rust流程控制

rust流程控制的具体使用

  更新时间:2023年12月07日 11:49:46  作者:int8 
在Rust中,控制流包括条件语句、循环和匹配模式等,用于实现程序的逻辑和流程控制,本文就来详细的介绍一下,感兴趣的可以了解一下

一、分支

(一)if

1.if
语法格式

if boolean_expression {
}

例子

fn main(){
let num:i32 = 5;
if num > 0 {
println!("正数");
}
}

条件表达式不需要用小括号。
条件表达式必须是bool类型。

2.if else

语法格式

if boolean_expression {
} else {
}

例子

fn main() {
let num = 12;
if num % 2==0 {
println!("偶数");
} else {
println!("奇数");
}
}

if else既可以作语句,又可以作表达式。当作表达式时,它的值是其分支代码块最后一个表达式的值。
我们可以在 let 语句的右侧使用它,例如:

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

值取决于哪个代码块被执行。这意味着 if 的每个分支的可能的返回值都必须是相同类型;
在上例中,if 分支和 else 分支的结果都是 i32 整型。如果它们的类型不匹配,如下面这个例子,则会出现一个错误:

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

3.if else if

语法格式

if boolean_expression1 {
} else if boolean_expression2 {
} else {
}

例子

fn main() {
let num = 2 ;
if num > 0 {
println!("{} is positive",num);
} else if num < 0 {
println!("{} is negative",num);
} else {
println!("{} is neither positive nor negative",num) ;
}
}

(二)if let

句法

IfLetExpression :
if let Pattern = Expression BlockExpression
(else ( BlockExpression | IfExpression | IfLetExpression ) )?

1.if let

语法格式

if let Pattern = Expression {
}

Pattern就是模式。
如果Pattern与Expression匹配,就执行相应的代码块。
可以使用操作符 | 指定多个模式。 这与match表达式中的 | 具有相同的语义

例子

enum E {
X(u8),
Y(u8),
Z(u8),
}
let v = E::Y(12);
if let E::X(n) | E::Y(n) = v {
assert_eq!(n, 12);
}

2.if let else

语法格式

if let Pattern = Expression {
} else {
}

例子

let dish = ("Ham", "Eggs");
if let ("Bacon", b) = dish {
println!("Bacon is served with {}", b);
} else {
println!("No bacon will be served");
}

if let else与if else一样既可以作语句,又可以作表达式。当作表达式时,它的值是其分支代码块最后一个表达式的值。

fn main() {
let x = Some(3);
let a = if let Some(1) = x { 1 } else { 5 };
println!("{a}");
}

3.if let else if let
语法格式

if let Pattern1 = Expression1 {
} else if let Pattern2 = Expression2 {
}else {
}

4.if和if let混合使用
语法格式

if let Pattern = Expression {
} else if boolean_expression{
}else {
}

例子

let x = Some(3);
let a = if let Some(1) = x {
1
} else if x == Some(2) {
2
} else if let Some(y) = x {
y
} else {
-1
};
assert_eq!(a, 3);

5.if let等价于match
例如:

if let PATS = EXPR {
/* body */
} else {
/*else */
}
等价于
match EXPR {
PATS => { /* body */ },
_ => { /* else */ }, // 如果没有else块,这相当于 `()`
}

在一些场合下,用match并不优雅,因为match必须考虑所有可能的值。
比如:

let optional = Some(7);
match optional {
Some(i) => {
println!("This is a really long string and `{:?}`", i);
},
_ => {}, // 必须有,因为 `match` 需要覆盖全部情况。不觉得这行很多余吗?
};

if let在这样的场合要简洁得多

fn main() {
let number = Some(7);
if let Some(i) = number {
println!("Matched {:?}!", i);
}
}

另一个好处是:if let允许匹配枚举非参数化的变量,即枚举未注明 #[derive(PartialEq)],我们也没有为其实现PartialEq。在这种情况下,通常if Foo::Bar==a会出错,因为此类枚举的实例不具有可比性。但是,if let是可行的。
你想挑战一下吗?使用if let修复以下示例:

// 该枚举故意未注明 `#[derive(PartialEq)]`,
// 并且也没为其实现 `PartialEq`。这就是为什么下面比较 `Foo::Bar==a` 会失败的原因。
enum Foo {Bar}
fn main() {
let a = Foo::Bar;
// 变量匹配Foo::Bar
if Foo::Bar == a {
// ^-- 这就是编译时发现的错误。使用 `if let` 来替换它。
println!("a is foobar");
}
}

(三)match

match用于检查值是否匹配一组模式中的某一个。似于C语言中的 switch 语句

语法格式

match variable_expression {
pattern1 => {
},
pattern2 => {
//
},
_ => {
// 默认
}
};

例子

fn main() {
let x = 1;
match x {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
4 => println!("four"),
5 => println!("five"),
_ => println!("something else"),
}
}

match既可以作语句,也可以作表达式,作表达式时,它把匹配分支代码块的最后一条表达式的结果当作返回值。
例子

fn main(){
let state_code = "MH";
let state = match state_code {
"MH" => "Maharashtra",
"KL" => "Kerala",
"KA" => "Karnadaka",
"GA" => "Goa",
_ => "Unknown"
};
println!("State name is {}",state);
}
运行结果
State name is Maharashtra

模式守卫
守卫出现在模式的后面,由关键字if后面的布尔类型表达式组成。
当模式匹配成功时,将执行守卫表达式。 只有此表达式的计算结果为真,才认为完全匹配成功。 否则,匹配将测试下一个模式,包括测试同一分支中运算符 | 分割的后续模式。

fn main() {
let maybe_digit = Some(8);
match maybe_digit {
Some(x) if x < 10 => println!("digit < 10"),
Some(x) => println!("digit >= 10"),
None => panic!(),
};
}

注意:使用操作符 | 的分支可能会导致后跟的守卫必须多次执行的副作用。 例如:

use std::cell::Cell;
let i = Cell::new(0i32);
match 1 {
1 | _ if { i.set(i.get() + 1); false } => {}
_ => {}
}
assert_eq!(i.get(), 2);

二、循环

(一)for

Rust 中的 for 只有 for in 这种格式,常用于遍历容器的元素
句法

IteratorLoopExpression :
for Pattern in Expression BlockExpression

pattern就是模式

例子
下面的代码,使用 for…in 循环,重复输出1到11之间的数字(不包括11)

fn main(){
for x in 1..11{
println!("x is {}",x);
}
}
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}

(二)while

句法

PredicateLoopExpression :
while Expression BlockExpression

例子
下面的代码,使用 while 循环重写下上面的代码,重复输出1到11之间的数字(不包括11)

fn main(){
let mut x = 1;
while x < 11{
println!("inside loop x value is {}",x);
x+=1;
}
println!("outside loop x value is {}",x);
}

(三)loop

loop 语句代表着一种死循环。
语法格式

loop {
}

范例
下面的语句,我们使用 loop 输出1到无限大的数字。

fn main(){
let mut x = 0;
loop {
x+=1;
println!("x={}",x);
}
}

(四)while let

句法

PredicatePatternLoopExpression :
while let Pattern = Expression BlockExpression

Pattern就是模式
如果值与模式匹配,则执行循环体块。如果不匹配,则跳出循环。

可以使用操作符 | 指定多个模式。

let mut vals = vec![2, 3, 1, 2, 2];
while let Some(v @ 1) | Some(v @ 2) = vals.pop() {
// 打印2, 2, 然后1
println!("{}", v);
}

例子

let mut x = vec![1, 2, 3];
while let Some(y) = x.pop() {
println!("y = {}", y);
}
while let _ = 5 {
println!("不可反驳模式总是会匹配成功");
break;
}

while let等价于包含match的loop。
如下:

while let PATS = EXPR {
/* loop body */
}
等价于
loop {
match EXPR {
PATS => { /* loop body */ },
_ => break,
}
}

三、循环标签

句法

LoopLabel :
LIFETIME_OR_LABEL :

一个循环表达式可以选择设置一个标签。这类标签被标记为循环表达式之前的生存期(标签),如 'foo: loop { break 'foo; }、'bar: while false {}、'humbug: for _ in 0…0 {}。 如果循环存在标签,则嵌套在该循环中的带此标签的break表达式和continue表达式可以退出此标签标记的循环层或将控制流返回至此标签标记的循环层的头部。

四、跳出循环

(一)break

句法

BreakExpression :
break LIFETIME_OR_LABEL? Expression?

当遇到break时,相关的循环体的执行将立即结束,例如:

let mut last = 0;
for x in 1..100 {
if x > 12 {
break;
}
last = x;
}
assert_eq!(last, 12);

break表达式只能跳出一层循环,如果要跳出多层循环,就要使用循环标签。
例如:

'outer: loop {
while true {
break 'outer;
}
}

break表达式只允许在循环体内使用,它有break、break 'label、break EXPR、break 'label EXPR这四种形式。

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

break 可以返回值
当使用loop循环时,可以使用break表达式从循环中返回一个值,通过形如break EXPR或break 'label EXPR来返回,其中EXPR是一个表达式。
其后不跟表达式的break与后跟 () 的break效果相同。
例如:

let (mut a, mut b) = (1, 1);
let result = loop {
if b > 10 {
break b;
}
let c = a + b;
a = b;
b = c;
};
// 斐波那契数列中第一个大于10的值:
assert_eq!(result, 13);

(二)continue

句法

ContinueExpression :
continue LIFETIME_OR_LABEL?

当遇到continue时,相关的循环体的当前迭代将立即结束,并将控制流返回到循环头。 在while循环的情况下,循环头是控制循环的条件表达式。 在for循环的情况下,循环头是控制循环的调用表达式。
与break一样,continue只能跳过一层循环,如果要跳过多层,可以使用continue 'label。
continue表达式只允许在循环体内部使用。

fn main(){
for x in 1..11{
if 5 == x {
continue;
}
println!("x is {}",x);
}
}

到此这篇关于rust流程控制的具体使用的文章就介绍到这了,更多相关rust流程控制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

    • 这篇文章主要为大家介绍了rust语言基础pub关键字及Some语法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
      2023-07-07
    • 结构体,是一种自定义数据类型,允许程序员将不同类型的数据结合起来,形成相关联的整体。Rust的结构体还提供方法和关联函数,可以指定那些与结构体数据相关的行为
      2022-10-10
    • 这篇文章主要介绍了rust 自动化测试、迭代器与闭包、智能指针、无畏并发,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
      2023-11-11
    • 所有权对大多数开发者而言是一个新颖的概念,它是 Rust 语言为高效使用内存而设计的语法机制。所有权概念是为了让 Rust 在编译阶段更有效地分析内存资源的有用性以实现内存管理而诞生的概念
      2023-01-01
    • 生命周期是Rust语言中的一个概念,用于决内存安全问题,本文主要介绍了一文弄懂rust生命周期,具有一定的参考价值,感兴趣的可以了解一下
      2023-12-12
    • Rust是一种现代的系统编程语言,它支持函数指针。函数指针是指向函数的指针,可以将函数作为参数传递给其他函数或存储在变量中。Rust中的函数指针可以用于实现回调函数、动态分发和多态等功能。本文将介绍Rust中的函数指针的基本用法和高级用法。
      2023-05-05
    • Rust并不像C++一样使用try catch的异常机制来进行错误处理,他将错误分为可恢复错误和不可恢复错误两类,主要使用panic!宏和Result<T,E>类型来进行错误处理,这篇文章主要介绍了Rust错误处理简介,需要的朋友可以参考下
      2022-11-11
    • 在win10上配置 Rust 开发环境(使用 mingw64编译器)和 idea 配置 Rust 插件的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
      2023-03-03
    • 这篇文章主要为大家介绍了Rust实现冒泡排序算法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
      2023-08-08
    • into_owned是Rust语言中std::borrow::Cow 枚举的一个方法,into_owned确保了调用者获得数据的独立所有权,无论Cow之前是引用还是已经拥有数据,本文给大家介绍Rust 的 into_owned() 方法,感兴趣的的朋友跟随小编一起看看吧
      2024-03-03

    最新评论