Hello Rust [1] - 基础语法
// 引入第三方包
use rand::Rng; // 随机测试包
use std::cmp::Ordering; // 比较值
use std::io; // 标准输入输出
fn main() {
println!("Guess the number!"); // 标准输出ÁÁÁÁ
// 不可变变量,生成一个1~100之间的随机数
let secret_number = rand::thread_rng().gen_range(1..=100);
// 循环
loop {
println!("Please input your guess.");
// 声明一个可变量,用mut关键字
let mut guess = String::new();
// 获取标准输入
io::stdin()
.read_line(&mut guess)
// 异常处理
.expect("Failed to read line");
// 将输入的字符串转换为数字并trim
// 这里的guess隐藏(shadowing)了之前的guess
// trim会消除空白符和换行符
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
// 处理无效输入
Err(_) => continue,
};
// 模板占位符
println!("You guessed: {guess}");
// 进行比较
match guess.cmp(&secret_number) {
// 比较结果太小
Ordering::Less => println!("Too small!"),
// 比较结果太大
Ordering::Greater => println!("Too big!"),
// 刚好相等,退出循环
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
变量
let x = 5; // 不可变量,类似js的const
let mut y = 6; // 变量
const z = 7; // 常量,类似c的宏定义
- 变量默认是不可变的。如果要可变则添加关键词
mut - 常量用
const声明。 - 常量与不可变量的区别:
- 常量不可用
mut - 常量可以在任何作用域声明,包括全局作用域。
- 常量只能被设置为常量表达式,而不可以是其他任何只能在运算时计算得到的值。
- 常量不可用
隐藏(shadowing)
let x = 5;
let x = x + 1; // 重新声明了x,对前一个申明的变量进行了隐藏
与使用mut的区别:
- 在shadowing场景下,重新声明的变量仍然是不可变的
- shadowing实际上是重新创建了一个新变量,此时是允许修改变量的类型的
数据类型
RUST 是静态类型语言,主要分成标量(scalar)类型和复合(copound)类型
标量类型
四种基本标量:
- 整型
- 浮点型
- 布尔类型
- 字符类型
整型
| 长度 | 有符号 | 无符号 |
|---|---|---|
| 8-bit | i8 | u8 |
| 16-bit | i16 | u16 |
| 32-bit | i32 | u32 |
| 64-bit | i64 | u64 |
| 128-bit | i128 | u128 |
| arch | isize | usize |
字面值,用来区分进制:
| 数字字面值 | 例子 |
|---|---|
| Decimal (十进制) | 98_222 |
| Hex (十六进制) | 0xff |
| Octal (八进制) | 0o77 |
| Binary (二进制) | 0b1111_0000 |
| Byte (单字节字符)(仅限于u8) | b'A' |
浮点型
let x = 2.0; // f64
let y: f32 = 3.0; // f32
- f32: 32位浮点数
- f64: 64位浮点数
布尔型
let t = true;
let f: bool = false;
字符类型
let c = 'z'; // 单引号,声明·char·字面量
复合类型
原生有两个复合类型:
- 元组(tuple):将一个或者多个其他类型的值组合到一个复合类型的主要方式,一旦声明,长度不变。
- 数组(array):每个元素类型必须相同,长度也是固定的。
元组
fn main() {
// 元素类型的定义
let tup: (i32, f64, u8) = (500, 6.4, 1);
// 解构语法
let (x, y, z) = tup;
// 直接访问
let fiv_hundred = x.0;Ï
let six_point_four = x.1;
let one = x.2;
}
没有任何值的元组,叫做单元(unit)元组,这种纸以及对应的类型都写成(),表示空之或者空的返回类型。
数组
fn main() {
// 指定类型
let a:[i32:5] = [1,2,3,4,5];
// 快速指定
let a = [3;5]; // [3,3,3,3,3]
// 访问元素
let first = a[0];
let second = a[1];
}
数组会在栈(stack)上分配空间而不是堆(heap),数组不如vector灵活,vector可以动态增长或者缩小长度。
访问时超出长度会报一个编译错误。
函数
fn main() {
print_labeled_measurement(5, 'h');
}
fn print_labeled_measurement(value: i32, unit_label: char) {
println!("The measurement is: {value}{unit_label}");
}
- 函数参数必须声明类型
语句和表达式
- 语句:执行操作但不返回值。
- 表达式:计算并产生一个值。
let y=6; // 这是一个语句,不返回值
// let x = (let y = 6); 所以会报错
let y = {
let x = 3;
// 这里是一个表达式,注意,表达式的结尾没有 ‘分号’,如果加上了分号,就变成了语句
x + 1
}; // 这里y的值为4;
- 表达式的结尾没有 ‘分号’,如果加上了分号,就变成了语句。
### 有返回值的函数 ```rust fn five() -> i32 5
fn main() { let x = five();
println!("The value of x is: {x}");
}
## 控制流
### if:条件
```rust
fn main() {
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}
- 在let语句中使用
if
fn main() {
let condition = true;
// 注意分支中的内容需要返回相同类型的值,不然就会报错
let number = if condition { 5 } else { 6 };
println!("The value of number is: {number}");
}
loop:循环
fn main() {
let mut count = 0;
// 使用 'xxx 作为循环标签
'counting_up: loop {
// 反复执行loop语句中的逻辑
println!("count = {count}");
let mut remaining = 10;
loop {
println!("remaining = {remaining}");
if remaining == 9 {
// 跳出当前loop
break;
}
if count == 2 {
// 跳出指定的loop
break 'counting_up;
}
remaining -= 1;
}
count += 1;
}
println!("End count = {count}");
}
while: 条件循环
fn main() {
let mut number = 3;
while number != 0 {
println!("{number}!");
number -= 1;
}
println!("LIFTOFF!!!");
}
for: 遍历循环
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}