基础概念 cargo 是rust的包管理工具 rustc 是rust的编译器 rustdoc 是rust的文档生成工具 rustfmt 是rust的代码格式化工具 rust-analyzer 是rust的智能补全工具
cargo cargo 是rust的包管理工具 cargo build 编译项目 cargo run 运行项目 cargo check 检查项目 cargo fmt 格式化代码 cargo clippy 检查代码 cargo doc 生成文档 cargo build –release 编译项目(优化) cargo clean 清理项目 cargo update 更新依赖 cargo add 添加依赖 cargo remove 删除依赖
1. 简单的hello 1 2 3 4 5 6 7 8 9 10 use ferris_says::say;use std::io::{stdout, BufWriter};fn main () { let out = "Hello fellow Rustaceans!" ; let width = 24 ; let mut writer = BufWriter::new (stdout ()); say (out, width, &mut writer).unwrap (); }
cargo run
#运行src/main.rs
也可以手动执行特定文件cargo run -- --src main1.rs
或者cargo run ./src/main1.rs
–bin 指定运行哪个二进制文件
std::io::{stdout, BufWriter}; std::io 为rust自带的标准库
提供
标准输入输出:如 stdin()、stdout()、stderr() 文件操作:如 File 类型用于读写文件
缓冲读写:如 BufReader、BufWriter 错误处理:如 Error 类型 其他工具:如 Cursor、Seek 等
1 2 let name = "Rust" ; println! ("Hello, {}!" , name);
println! 是rust的标准库提供的宏,用于打印信息到控制台 println! 后面的感叹号表示它是一个宏,用于格式化输出。宏是 Rust 中非常强大的工具,可以处理比普通函数更复杂的逻辑。
2. 第一个关键点, 所以权系统 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 use std::io;fn main () { println! ("Guess the number!" ); println! ("Please input your guess." );1 let mut guess = String::new (); io::stdin () .read_line (&mut guess) .expect ("Failed to read line" ); println! ("You guessed: {}" , guess); }
关键内容在&mut guess
这是一个对guess的引用,& 表示引用,mut 表示可变引用。, 如果传递的是不可变引用(&guess),则不能修改guess的值。,
Rust 的所有权系统确保内存安全。通过传递可变引用(&mut guess),read_line 可以借用 guess 并修改它,而不会获取 guess 的所有权。 这样,guess 的所有权仍然在 main 函数中,read_line 只是临时借用它。
声明数字类型let guess_number: u32 = 42;
3. Mut 声明 1.关键点
是否可变
是否可修改
声明变量的时候, 使用mut, 代表是可变变量 , 可以修改, 使用可变变量的时候, &mut是可以修改原本的值, 而&value只能访问
Eg:
1 2 3 4 5 6 7 8 9 10 11 let x = 5 ; let mut y = 5 ; y = 6 ; let mut value = String ::from ("hello" );let ref1 = &value; let ref2 = &mut value;
注意
增加引用之后就要使用引用值, 没增加引用的话可以直接使用, 当一个值被可变借用时,在这个借用的生命周期内,我们不能直接修改原值。
❌
1 2 3 4 5 6 7 fn misxTable (){ let mut value = 1 ; let mutValue = &mut value; value = 2 ; } `value` is assigned to here but it was already borrowed
此处第二个错误 fn misxTable(){ | ^^^^^^^^^ help: convert the identifier to snake case: misx_table
这是 Rust 的命名规范警告。在 Rust 中,函数名应该使用蛇形命名法(snake_case)
✅
1 2 3 4 5 6 fn correct_fn (){ let mut value = 1 ; let mut_value = &mut value; *mut_value = 2 ; println! ("mut_value: {}" , mut_value); }
2. 如何改变可变引用值
1 2 3 4 5 6 7 fn current_eg (){ let mut value = 1 ; let mut_value = &mut value; *mut_value = 2 ; println! ("user * to change value mut: {}" , mut_value) }
1 2 3 4 5 6 7 8 9 fn othen_eg (){ let mut value = 2 ; { let mut_vallue = &mut value; *mut_value = 3 ; } println ("use this to change mut_value: {}" , value) }
Eg1: 实现一个简单的计算器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 use std::io;fn main (){ print_fn () } fn handle_operation (code: &str , num1: i32 , num2: i32 ) -> i32 { println! ("code:{}" , code); match code.trim () { "+" => add (num1, num2), "-" => sub (num1, num2), "*" => mul (num1, num2), "/" => div (num1, num2), _ => 0 , } } fn add (a: i32 , b:i32 ) -> i32 { a + b } fn sub (a: i32 , b:i32 ) -> i32 { a - b } fn mul (a: i32 , b: i32 ) -> i32 { a * b } fn div (a: i32 , b: i32 ) -> i32 { a / b } fn judgeCode (code: &str ) -> bool { match code.trim () { "=" => true , _ => false , } } fn print_fn () { let mut pause = String::from ("+" ); let mut switch_flag = false ; let mut mul_number = String::new (); let mut result = 0 ; while pause.trim () != "=" { println! ("pause: {}" , pause); match switch_flag { true => { println! ("now need input a mul code(+-*/):" ); pause.clear (); io::stdin ().read_line (&mut pause).expect ("读取失败" ); switch_flag = false ; }, false => { println! ("now need input a number:" ); io::stdin ().read_line (&mut mul_number).expect ("读取失败" ); let number : i32 = mul_number.trim ().parse ().expect ("请输入数字" ); result = handle_operation (&pause, result, number); switch_flag = true ; mul_number.clear (); }, } } println! ("最终结果: {}" , result); }
知识点
接受输入的时候需要trim
函数最后一个不带;的表达式, 是返回值
3. 如何执行强制类型转换
let number: i32 = mul_number.trim().parse().expect(“请输入数字”);
1 2 3 4 let number : i32 = mul_number .trim () .parse () .expect ("请输入数字" );
等效于
1 let number **=** mul_number**.**trim ()**.**parse**::**<*i32 *>()**.**expect ("请输入数字" );
match转换
1 2 3 4 5 6 7 let number :i32 =match guess_num.trim ().parse () { Ok (num) => num, Err (_) => { println! ("请输入数字!" ); continue ; } };
match
处理错误更加友好, 不会中断
1
// 创建包含初始值 “+” 的字符串(已分配内存)
let with_plus = String**::**from(“+”);
// 创建空字符串(尚未分配堆内存)
let empty = String**::**new();
fn print_fn() {
// 当需要初始操作符时(推荐当前案例使用这个)
let mut pause = String**::**from(“+”);
// 当需要全新空缓冲区时(适合接收用户即时输入)
let mut input_buffer = String**::**new();
// … 其余代码 …
}
4.数据类型 1 2 3 4 5 6 7 8 9 let bool :bool = true ; let int :i32 = 1 ; let float :f32 = 1.0 ; let str :String = "hello" .to_string (); let char :char = 'h' ; let array :[i32 ;5 ] = [1 ,2 ,3 ,4 ,5 ]; let tuple :(i32 ,f32 ,char ) = (1 ,1.0 ,'h' ); let slice :&[i32 ] = &array[0 ..2 ]; let mut_slice :&mut [i32 ] = &mut array[0 ..2 ];
5.逻辑 if else ❌
1 2 3 4 5 6 7 fn main () { let number = 3 ; if number { println! ("number was three" ); } }
if后面必须是bool
✅
1 2 3 4 5 6 7 8 9 10 11 12 13 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" ); } }
1. 三元替代 1 const a = if (10 ) {10 } else {-10 }
if 和 else 后面的类型需要一致
2.match 1 2 3 4 5 6 7 let number :i32 =match guess_num.trim ().parse () { Ok (num) => num, Err (_) => { println! ("请输入数字!" ); continue ; } };
eg2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 use rand::Rng;use std::io;use std::cmp::Ordering;fn main (){ loop { println! ("gugess a number: (0-10)" ); let random_num = rand::thread_rng ().gen_range (0 ..=10 ); let mut guess_num = String::new (); io::stdin ().read_line (&mut guess_num).expect ("failed to read line" ); let number :i32 =match guess_num.trim ().parse () { Ok (num) => num, Err (_) => { println! ("请输入数字!" ); continue ; } }; match number.cmp (&random_num){ Ordering::Less => { println! ("too small: {}" , random_num); }, Ordering::Greater => { println! ("too big: {}" , random_num); }, Ordering::Equal => { println! ("you win" ); break ; } } } }