rust简介、变量类型、流程控制


学习视频:B站

简介

Rust擅长的领域:

  • 高性能Web Service
  • 命令行工具
  • 网络编程
  • 嵌入式设备
  • 系统编程

Rust最初是Mozilla公司的一个研究项目。

Rust优点:性能、安全性、并发。缺点:难学,有很多独有的概念。

hello world

fn main() {
    println!("Hello World")
}
$ rustc main.rs
$ ./main.exe

Cargo

Rust的构建系统和包管理工具。

$ cargo --version
cargo 1.65.0 (4bc8f24d3 2022-10-20)

创建项目:

$ cargo new hello_cargo
Created binary (application) `hello_cargo` package

image-20221116173735960

源代码在src文件夹下,顶层目录防止和源码无关的文件。

Cargo.toml

Cargo的配置格式

[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

构建项目:cargo build

运行项目:cargo run,编译代码+执行结果。

PS H:\rust\hello_cargo> cargo run
   Compiling hello_cargo v0.1.0 (H:\rust\hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 0.84s
     Running `target\debug\hello_cargo.exe`
Hello, world!

cargo check检查代码,确保编译通过,但是不产生执行文件,比cargo build快的多,可以反复使用校验代码。

为发布构建:cargo build --release,编译会进行优化,更慢

猜数游戏

生成随机数,玩家猜测,提示偏大偏小,直至猜对。

猜一次数

use std::io;

fn main() {
    println!("猜数!");

    // rust 默认所有变量不可变
    //let foo = 1; // foo不可变了

    // 加上mut就可变
    let mut guess = String::new();

    io::stdin().read_line(&mut guess).expect("无法读取行");
    // io::Result 0K,Err

    println!("你猜的数是:{}",guess);
}

生成一个随机数

rust标准库没有生成随机数的函数,但是有库可用。

在cargo.html加入随机数包:

[package]
name = "guessing_game"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.7.0"

代码:

use std::io;

use rand::Rng;

fn main() {
    println!("猜数!");

    
    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("神秘数字是:{}",secret_number);
    
    let mut guess = String::new();

    io::stdin().read_line(&mut guess).expect("无法读取行");
    // io::Result 0K,Err

    println!("你猜的数是:{}",guess);
}

两数比较

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("猜数!");

    
    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("神秘数字是:{}",secret_number);
    
    let mut guess = String::new();

    io::stdin().read_line(&mut guess).expect("无法读取行");
    // io::Result 0K,Err

    // 字符串转整数 shadow 可以复用变量名
    // 显式声明变量类型
    let guess:i32 = guess.trim().parse().expect("请输入数字");

    println!("你猜的数是:{}",guess);

    match guess.cmp(&secret_number) {
        Ordering::Less => println!("Too small!"),
        Ordering::Greater => println!("Too big!"),
        Ordering::Equal => println!("You win!"),
    }
}

多次猜测

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
    println!("猜数!");

    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("神秘数字是:{}",secret_number);

    loop {
        let mut guess = String::new();

        io::stdin().read_line(&mut guess).expect("无法读取行");
        // io::Result 0K,Err
    
        // 字符串转整数 shadow 可以复用变量名
        // 显式声明变量类型
        let guess:i32 = match guess.trim().parse() {
            Ok(num) => num,
            Err(_) => continue,
        };
    
        println!("你猜的数是:{}",guess);
    
        match guess.cmp(&secret_number) {
            Ordering::Less => println!("Too small!"),
            Ordering::Greater => println!("Too big!"),
            Ordering::Equal => {
                println!("You win!");
                break;
            },
        }
    }
}

通用编程概念

不可变变量:

image-20221116193548243

常量:

大写,const,类型

const MAX_POINTS:i32 = 100_000;

Shadowing,使用相同的变量名,但是不同类型,隐藏之前的同名变量。

// 不可
let x = 5;
x = 6;

// 可以
let x = 5;
let x = 6;

标量类型:

  • 整数,u32,i32。。。

    image-20221116194551903

    调试模式下溢出会panic,发布模式下不会panic,会环绕,也就是8位0-255如果是256的话,会变成1。

  • 浮点数,32,64,默认64。

  • 布尔类型,一个字节大小,true,false。

  • 字符类型,四个字节,unicode标量值。

复合类型:

  • Tuple,[美]tʌpl,长度固定,可以多个类型的多个值放入一个类型。

    fn main() {
        let tup:(i32,f64,i32) = (500,1.2,3);
        let (x,y,z) = tup;
        println!("{} {} {}",x,y,z);
        println!("{} {} {}",tup.0,tup.1,tup.2);
    }
    
  • 数组,长度固定,类型相同

    image-20221116195909151

    fn main() {
        let a = [1;3]; // 重复元素简化写法
        println!("{:#?}",a);
    }
    // [
    //     1,
    //     1,
    //     1,
    // ]    
    

    索引超界,编译会通过(不保证正确),运行会报错,不允许访问对应的内存。

函数:

fn main() {
    let a = [1,2,3];
    nice_print(a[1]); //整数2
}

fn nice_print(x:i32) {
    println!("整数{}",x);
}

返回值:fn最后一个表达式的值。

fn plus_five(x:i32) -> i32 {
    x + 5
}

控制流:

fn main() {
    let a = 5;
    if a < 3 {
        println!("<3");
    } else {
        println!(">=3");
    }
}

选择赋值:

fn main() {
    let condition = true;

    let number = if condition {5} else {6};
    println!("the value of number is: {}",number); //5
}

循环:loop,while,for

fn main() {
    let mut number = 3;
    while number != 0 {
        println!("{}",number);
        number = number-1;
    }
    
    let a = [1,2,3,4,5];
    // 用的最多
    for element in a.iter() {
        println!("{}",element);
    }
    
    for number in (1..4) {
        println!("{}",number);
    }
}