在师兄们的蛊惑下,从C转RUST了,应该差不多吧
一、变量
1、基本介绍
(1)常量
const
常量
- 定义方式:使用
const
关键字,后面紧跟常量名、冒号、类型注解和等号,最后是常量值。例如const MAX_POINTS: u32 = 1000;
。 - 特点
- 编译时确定:在编译时,编译器就知道它的值,这使得 Rust 能在编译阶段进行更多的优化。
- 值复制:每次使用
const
常量时,实际上是复制了一份常量的值。 - 不可变:其值一旦定义就不能改变,确保了代码中使用该常量的部分不会意外修改它。
- 适用场景:适用于那些在代码中需要多次使用的固定值,如数学常数、配置参数等。
static
常量
- 定义方式:使用
static
关键字,定义格式与const
类似。例如static MESSAGE: &'static str = "Hello, World!";
。 - 特点
- 生命周期为
'static
:意味着该常量在整个程序的运行期间都存在。 - 单实例:所有对
static
常量的引用都指向同一个内存地址。 - 可变选项:可以使用
static mut
定义可变的静态变量,但访问和修改这种变量需要使用unsafe
代码块,因为它可能会引发数据竞争问题。
- 生命周期为
- 适用场景:当需要在程序的不同部分共享同一个值,或者需要在运行时初始化常量时,可以使用
static
常量。
(2)不变变量
如果一个变量的值不需要改变,那么我们可以使用不变变量。用法:
let a = 123;
(3)可变变量
要声明一个可变变量,只要使用关键词 mut 即可。
let mut a = 123;
(4)数据类型
rust在声明变量时不一定要声明变量类型,大多数情况都可以自动判断,但是也可以声明,有些情况可能会无法自动判断,以下是rust中的数据类型
类型分类 | 具体类型 | 描述 | 示例 | |
---|---|---|---|---|
标量类型 | 整数类型 | 用于表示整数,有不同的位数和符号性 | i8 (8 位有符号整数),u8 (8 位无符号整数),i16 ,u16 ,i32 ,u32 ,i64 ,u64 ,i128 ,u128 ,isize (指针大小的有符号整数),usize (指针大小的无符号整数) | let num: i32 = 42; |
浮点类型 | 用于表示小数,有单精度和双精度之分 | f32 (单精度),f64 (双精度) | let pi: f64 = 3.14159; | |
布尔类型 | 只有两个可能的值:true 和 false | bool | let is_valid: bool = true; | |
字符类型 | 表示单个 Unicode 字符,用单引号括起来 | char | let letter: char = 'A'; | |
复合类型 | 元组类型 | 可以将不同类型的值组合在一起,长度固定 | 例如 (i32, f64, bool) | let tup: (i32, f64, bool) = (500, 6.4, true); |
数组类型 | 包含多个相同类型的值,长度固定 | 例如 [i32; 5] 表示包含 5 个 i32 类型元素的数组 | let arr: [i32; 3] = [1, 2, 3]; | |
集合类型 | 向量(Vec ) | 类似于动态数组,可以在运行时改变长度,只能存储相同类型的值 | Vec<T> ,其中 T 是元素类型 | let mut vec: Vec<i32> = vec![1, 2, 3]; |
字符串(String ) | 可变的 UTF – 8 编码字符串 | String | let mut s = String::from("hello"); | |
哈希映射(HashMap ) | 存储键值对,键和值可以是不同类型,通过键来快速查找值 | HashMap<K, V> ,其中 K 是键的类型,V 是值的类型 | rust<br>use std::collections::HashMap;<br>let mut map = HashMap::new();<br>map.insert("key", 1);<br> | |
指针类型 | 引用 | 指向另一个值而不拥有它,有不可变引用 &T 和可变引用 &mut T | &T ,&mut T | rust<br>let x = 5;<br>let ref_x = &x;<br> |
原始指针 | 有不可变原始指针 *const T 和可变原始指针 *mut T ,通常用于与底层代码交互,使用时需要 unsafe 代码块 | *const T ,*mut T | rust<br>let x = 5;<br>let raw_ptr: *const i32 = &x as *const i32;<br> | |
自定义类型 | 结构体(struct ) | 可以将多个不同类型的值组合成一个新的类型,有具名结构体、元组结构体和单元结构体三种形式 | rust<br>struct Point {<br> x: i32,<br> y: i32<br>}<br> | |
枚举(enum ) | 定义一组可能的值 | rust<br>enum Color {<br> Red,<br> Green,<br> Blue<br>}<br> | ||
类型别名 | 为现有类型创建一个新的名称 | 例如 type Kilometers = i32; | type Kilometers = i32; let distance: Kilometers = 10; |
只需要在变量后面使用冒号声明类型即可,例如
let x: i32 = 42;
let y: f64 = 3.14;
let is_true: bool = true;
let letter: char = 'A';
二、函数
在rust中声明变量使用 fn
,同时使用 ->
声明返回值的类型,例如
fn add_numbers(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let result = add_numbers(3, 5);
println!("两数相加的结果是: {}", result);
}
三、条件、循环语句
rust中的 if ,while ,for 语句和c语言几乎没区别,就不说了。在其他语言中的 switch 语句在rust中是更强大的 match 语句,没有 do……while 语句
loop循环
这也是rust中特有的一个循环,loop是一个无限循环,我们可以在需要不断循环的地方使用,例如程序的主程序。
match 语句
1. 匹配整数类型
在 Rust 里,match
语句能对整数进行精确匹配,也可使用通配符 _
来处理未匹配的情况。
fn main() {
let number = 2;
match number {
1 => println!("数字是 1"),
2 => println!("数字是 2"),
3 => println!("数字是 3"),
_ => println!("数字不是 1、2 或 3"),
}
}
解释:
- 定义了一个整数变量
number
并赋值为2
。 match
语句对number
的值进行匹配。当number
为1
、2
或3
时,会执行对应的代码块。_
是通配符,若number
的值不是1
、2
或3
,则会执行_
分支的代码。
2. 匹配枚举类型(暂时不涉及)
枚举类型在 Rust 中经常使用,match
语句能很好地对其进行匹配。
// 定义一个 Color 枚举类型
enum Color {
Red,
Green,
Blue,
}
fn main() {
let my_color = Color::Green;
match my_color {
Color::Red => println!("颜色是红色"),
Color::Green => println!("颜色是绿色"),
Color::Blue => println!("颜色是蓝色"),
}
}
解释:
- 定义了一个
Color
枚举类型,包含Red
、Green
和Blue
三个成员。 - 创建了一个
my_color
变量并赋值为Color::Green
。 match
语句对my_color
进行匹配,根据不同的枚举成员执行相应的代码块。
3. 匹配元组类型
match
语句可以对元组类型进行匹配,同时匹配元组中的多个元素。
fn main() {
let point = (1, 2);
match point {
(0, 0) => println!("点在原点"),
(x, 0) => println!("点在 x 轴上,x 的值是 {}", x),
(0, y) => println!("点在 y 轴上,y 的值是 {}", y),
(x, y) => println!("点的坐标是 ({}, {})", x, y),
}
}
解释:
- 定义了一个
point
元组,其值为(1, 2)
。 match
语句对point
进行匹配,根据不同的坐标情况执行相应的代码块。例如,当元组为(0, 0)
时,表明点在原点;当元组为(x, 0)
时,表明点在 x 轴上。
4. 匹配结构体类型
match
语句还能对结构体类型进行匹配,并且可以结合条件进行更复杂的匹配。
// 定义一个 Person 结构体
struct Person {
name: String,
age: u8,
}
fn main() {
let person = Person {
name: String::from("Alice"),
age: 25,
};
match person {
Person { name, age } if age < 18 => println!("{} 是未成年人", name),
Person { name, age } => println!("{} 是成年人,年龄是 {}", name, age),
}
}
解释:
- 定义了一个
Person
结构体,包含name
和age
两个字段。 - 创建了一个
person
实例,其姓名为"Alice"
,年龄为25
。 match
语句对person
进行匹配,使用if
条件判断age
是否小于18
。若小于18
,则输出该人为未成年人;否则,输出该人为成年人及对应的年龄
枚举类型有点难,没看懂,后面再来研究
四、初步实操
(1)一个简单计算器
创建一个计算器支持四则运算
use std::io;
fn main() {
loop {
println!("请输入第一个数字:");
let num1 = get_input_number();
println!("请输入运算符 (+, -, *, /):");
let operator = get_input_operator();
println!("请输入第二个数字:");
let num2 = get_input_number();
let result = match operator {
'+' => num1 + num2,
'-' => num1 - num2,
'*' => num1 * num2,
'/' => {
if num2 == 0.0 {
println!("错误: 除数不能为零。");
continue;
}
num1 / num2
}
_ => {
println!("错误: 无效的运算符。");
continue;
}
};
println!("结果: {} {} {} = {}", num1, operator, num2, result);
println!("是否继续计算? (y/n)");
let continue_choice = get_input_choice();
if continue_choice != 'y' {
break;
}
}
println!("感谢使用计算器!");
}
fn get_input_number() -> f64 {
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("读取输入时出错");
match input.trim().parse::<f64>() {
Ok(num) => return num,
Err(_) => println!("错误: 请输入有效的数字。"),
}
}
}
fn get_input_operator() -> char {
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("读取输入时出错");
let input_char = input.trim().chars().next();
match input_char {
Some(op) if "+-*/".contains(op) => return op,
_ => println!("错误: 请输入有效的运算符 (+, -, *, /)。"),
}
}
}
fn get_input_choice() -> char {
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("读取输入时出错");
let input_char = input.trim().chars().next();
match input_char {
Some(choice) if "yn".contains(choice) => return choice,
_ => println!("错误: 请输入 'y' 或 'n'。"),
}
}
}
我们定义一个主函数,并在其中加入无限循环,实现了主程序的不断运行,同时定义了get_input_number
,get_input_operator
,get_input_choice
函数,分别用于获取输入的数字,获取运算符以及获取是否需要继续计算的选项
使用
rustc xxxxxx.rs
编译源代码
最终效果
