跳到主要内容

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声明。
  • 常量与不可变量的区别:
    1. 常量不可用mut
    2. 常量可以在任何作用域声明,包括全局作用域。
    3. 常量只能被设置为常量表达式,而不可以是其他任何只能在运算时计算得到的值。

隐藏(shadowing)

let x = 5;

let x = x + 1; // 重新声明了x,对前一个申明的变量进行了隐藏

与使用mut的区别:

  • 在shadowing场景下,重新声明的变量仍然是不可变的
  • shadowing实际上是重新创建了一个新变量,此时是允许修改变量的类型的

数据类型

RUST 是静态类型语言,主要分成标量(scalar)类型和复合(copound)类型

标量类型

四种基本标量:

  • 整型
  • 浮点型
  • 布尔类型
  • 字符类型

整型

长度有符号无符号
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

字面值,用来区分进制:

数字字面值例子
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}");
}
}