前言
任何一门编程语言几乎都脱离不了:变量、基本类型、函数、注释、循环、条件判断,这是一门编程语言的语法基础,只有当掌握这些基础语法及概念才能更好的学习 Rust。
条件判断
if 表达式
if
语句在其他语言中很常见,这里不再多做解释,看注释即可。
// 判断 n 是否小于 0
if n < 0 {
// 当 n 小于 0 时执行这句
print!("{} 是负数", n);
} else {
// 否则执行这句
print!("{} 是 0", n);
}
if
表达式也支持 if...else if...else
语句:
// 判断是否满足 if 条件1
if condition1 {
// ...
} else if condition2 { // 当不满足 条件1 时,判断是否满足条件2
// ...
} else { // 条件1 和 条件2 都不满足时
// ...
}
在 Rust 中,没有像其他语言那样的三元表达式(三目运算符),但是在 Rust if
是一个表达式,这意味着可以在 let
语句中使用它来对变量进行条件赋值,从而达到类似三元表达式的效果。
let condition = true;
// number 的类型必须明确,因此两个分支的返回值类型必须一致
let number = if condition { 5 } else { 6 };
println!("The value of number is: {}", number);
模式匹配(match 表达式)
虽然严格来说 match
并不是条件判断,但它常作为 Rust 的条件控制结构,其功能类似于其他语言中的 switch / case
语句。match
针对一个值执行模式匹配,并根据匹配到的模式执行相应的代码。
let value = some_val();
match value {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("anything"), // _ 类似于其他语言中的 default,用来匹配所有其它情况
}
match
匹配必须是穷尽的(exhaustive),也就是说所有可能的值都必须被考虑。使用 _
模式可以捕捉所有未显式处理的值。
match
守卫(match guards)允许你为同一个 match
分支添加额外的条件判断,这样就可以基于值的属性做更精细的控制。
match some_val {
val if val < 5 => println!("less than five"),
val => println!("{}", val),
}
循环语句
loop 循环
loop
关键字创建了一个无限循环,它会不断地重复代码块,直到明确地通过 break
关键字退出循环。
let mut counter = 0;
loop {
counter += 1;
if counter == 10 {
break;
}
};
loop
也能返回一个值,这个值是在 break
后跟着的表达式。
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // 当 counter 达到 10 时退出循环,并返回 counter 的两倍
}
};
println!("The result is {}", result); // 输出:The result is 20
while 循环
while
循环在循环的每次迭代开始前检查条件表达式,只有当条件为真时才会执行循环体。如果条件为假,则退出循环。
let mut number = 3;
while number != 0 {
println!("{}", number);
number -= 1;
}
和其他语言不一样在,Rust 中没有 do...while
语句,如果想要实现类似的效果可以通过 loop
+ if
模拟。
let mut count = 0;
loop {
count += 1;
println!("这是第 {} 次迭代", count);
// 判断条件,如果条件不满足,则退出循环
if count >= 10 {
break;
}
}
for 循环
for
循环是开发中使用最频繁的循环,尤其是需要迭代一个序列或迭代器时。对于集合中的每个元素,它都会执行一次循环体。for
循环更加安全和高效,而且它不会产生越界的风险。
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("the value is: {}", element);
}
for 语句的特点
Rust 语言中的 for
循环不支持传统的 C/C++ 风格的 for (initialization; condition; update)
循环。在 Rust 中,for
循环被设计成基于迭代器的,这意味着它是用来遍历迭代器中的元素。之所以这样设计,是为了更安全和直接地处理集合中的元素,而不需要像在 C/C++ 中那样手动管理索引。
如果你想要执行类似于 for (int i = 0; i < 10; i++)
的循环,Rust 提供了一个 Range
类型,可以通过这个类型的 ..
或 ..=
(包含上界)运算符来创建。
Rust 的 for
循环进行迭代示例如下:
// 使用 `..` 创建一个左闭右开的范围(0 到 9)
for i in 0..10 {
println!("Value of i is: {}", i);
}
// 使用 `..=` 创建一个闭区间的范围(0 到 10)
for i in 0..=10 {
println!("Value of i is: {}", i);
}
注意:Range
类型产生的数值并不包括区间的上界,需要使用 ..=
语法才可以。当需要类似 C/C++ 风格的循环控制时,通常可以使用 Range
类型,这种方式也避免了因手动处理索引导致类似越界访问的错误。
Range 类型
在 Rust 中,Range
是一种迭代器类型,它生成一系列按顺序排列的数字。Range
通常用于 for
循环中,提供了一种简便的方式来执行重复操作一定次数的任务。
这里有两种最常用的 Range
类型:
Range
(start..end
): 创建一个从start
到end
(不包括)的迭代器,也就是左闭右开的区间。RangeInclusive
(start..=end
): 创建一个从start
到end
(包括)的迭代器,闭区间,包含结束值。
创建 Range
:
Range
通过使用两个点 ..
运算符来创建:
let a = 0..5; // 这将包括整数 0, 1, 2, 3, 4
for i in a {
println!("{}", i); // 打印 0 到 4。
}
创建 RangeInclusive
:
RangeInclusive
通过使用三个点 ..=
运算符来创建:
let b = 0..=5; // 这将包括整数 0, 1, 2, 3, 4, 5
for i in a {
println!("{}", i); // 打印 0 到 5。
}
这两种类型都是迭代器,可以使用它们的 next
方法来逐个获取值,或者使用 for
循环来遍历这些值。
常用方法
Range
类型支持很多操作方法,下面列举几个常用的。
rev
rev
方法可以用来反转范围,创建一个新的迭代器,它会按照相反的顺序产生数值。
let range = (1..10).rev();
for num in range {
println!("{num}"); // 将从 9 递减到 1
}
count
返回迭代器中剩余的元素数量。
let range_cnt = (1..100).count();
println!("{range_cnt}"); // 输出: 99
start_bound
和 end_bound
返回Range
的起始边界和结束边界。返回的是一个Bound
枚举,可以是Included
(包含边界值)或Excluded
(不包含边界值)。
let range = 1..100;
println!("{:?}", range.start_bound()); // 输出: Included(1)
println!("{:?}", range.end_bound()); // 输出: Excluded(100)
contains
判断一个指定的数值是否在Range
内。如果是start..end
类型的Range
,会判断这个值是否大于等于start
且小于end
。
let range = 1..100;
println!("{}", range.contains(&50)); // 输出: true
println!("{}", range.contains(&100)); // 输出: false
next
迭代Range
并返回下一个值,如果迭代已经完成则返回None
。
let mut range = 1..3;
assert_eq!(range.next(), Some(1));
assert_eq!(range.next(), Some(2));
assert_eq!(range.next(), None);
last
返回Range
中的最后一个数值,对 start..end
类型的Range
来说,这个值是end - 1
。
let range = 1..100;
println!("{}", range.last().unwrap()); // 输出: 99
nth
获取迭代器中的第n
个元素,并且将迭代器前进到此位置后面的元素。
let mut range = 1..100;
println!("{}", range.nth(49).unwrap()); // 输出: 50,即第50个元素
step_by
创建一个每n
个数值产生一次的迭代器。
let range = (0..10).step_by(3);
for num in range {
println!("{num}"); // 输出: 0, 3, 6, 9
}
其他
这个只列举了最常用的一些方法,Range 还支持很多其他的方法,此外,由于 Range
和 RangeInclusive
实现了 Iterator
trait,因此提供了所有迭代器的标准方法,如 map
, filter
, fold
, 和 collect
等。
结语
本章介绍了条件判断、循环语句以及 Range 类型,这是在程序开发中最常用的语句。在 Rust 中,不支持 do...while
、for ( i = 0; i <10; i++ )
、三元运算符
这类语法,但是可以用其他语法平替,这是从其他语言切换到 Rust 开发时需要注意的。