Day 03 - 结构与枚举

本贴最后更新于 602 天前,其中的信息可能已经时异事殊

image

img

📚 结构

创建时间:2023-03-29 20:30 星期三


基础使用

关于结构的定义与使用的方法是:

struct User {
    username: String,
    age: i32,
    is_life: bool,
}

fn main() {
    let xxx = User {
        username: String::from("xxx"),
        age: 21,
        is_life: true
    };
}

在创建一个结构体变量的时候你不必一一对应结构体的申明但是你需要全部列出也就是你不能这么写:

struct User {
    username: String,
    age: i32,
    is_life: bool,
}

fn main() {
    let xxx = User {
        username: String::from("xxx"),
        is_life: true
    };
} // 少了个age报错

接下来我们做一个结构 的读写 demo

struct User {
    username: String,
    age: i32,
    is_life: bool,
}

fn main() {
    let mut xxx = User {
        username: String::from("xxx"),
        age: 21,
        is_life: false
    };

    liuboyuan.username = String::from("不知名的家伙") ;

    print!("这厮叫做: {}, 今年{}岁, {}",xxx.username,xxx.age,if xxx.is_life{"一个黄毛小子竟然还活着"} else {"幸好它死了"});
}

Rust 的结构体中 实例为可变的时候 实例所有的属性都是可变的 实例不可变的时候 所有属性都是不可变的

当我们在创建某个 struct 的实例的时候,当属性名称和属性值相同的时候 比如:

let mut User = UserStruct{
	password: password,
};

可以这么简写

let mut User = UserStruct{
	password,
};

struct User {
    username: String,
    password: String,
    is_life: bool,
}

fn main() {
    let username: String = String::from("文明");
    let mut UserInstance = User{
        username,
        password: String::from("你好"),
        is_life: true,
    };
  
    print!(
        "你好我是:{} , 我的密码后三位是:{}, 我的存活状态: {}",
        UserInstance.username,
        UserInstance.password,
        UserInstance.is_life
    );
}

组合

结构的属性可以进行组合

let template = XXX{
	...
}
let mu = XXX {
	xxx: xxx,
	xxxx, xxx,
	..template,
}

比如代码:

struct User {
    username: String,
    password: String,
    is_life: bool,
}

fn main() {
    let lifeuser = User {
        username: String::from("新用户哦"),
        password: String::from("新用户哦"),
        is_life: true,
    };

    let user1 = User{
        username: String::from("刘秀"),
        password: String::from("刘秀的密码"),
        ..lifeuser  // 组合状态
    };

    print!("{} 状态 : {}", user1.username, user1.is_life);
}

Tuple Struct

struct RGB(i32,i32,i32);

fn main() {
    let red = RGB(255, 0 ,0);

    print!("{},{},{}",red.0,red.1,red.2);  
}

我们可以不给结构的字段加上名字 但是这样我们需要一一对应。

Struct 的 所有权

该 Struct 实例拥有里面所有数据的所有权, 只要结构是有效的那么字段也是有效的。

Struct 是可以存储引用的但是需要使用生命周期进行操作,这里先不讲。

示例

use std::io;

struct changFangXing{
    width: u32,
    height: u32
}

fn main(){
    println!("请输入一个宽: ");
    let mut val = String::new();
    io::stdin().read_line(&mut val).expect("错误!");
    let width : u32= match val.trim().parse() {
        Result::Ok(num)=> {
            num
        },
        Result::Err(_)=>{
            print!("你输入的数字有错误!");
            return;
        }
    };
    println!("请输入一个长: ");
    let mut val = String::new();
    io::stdin().read_line(&mut val).expect("错误!");
    let height : u32= match val.trim().parse() {
        Result::Ok(num)=> {
            num
        },
        Result::Err(_)=>{
            print!("你输入的数字有错误!");
            return;
        }
    };
  
    let cfx = changFangXing{
        width,
        height
    };

    print!("你的宽是:{}, 你的长是:{}, 你的面积是:{}", cfx.width, cfx.height, cfx.width * cfx.height);
}

打印 Struct

要是用 print!宏打印的代码需要实现一个 Display 也就是使用以下的语法进行打印:

print!("{:?}", User)

当然打印 Struct 还需要进行 Debug 的实现。

use std::io;

#[derive(Debug)]
struct changFangXing{
    width: u32,
    height: u32
}

fn main(){
    ...
    print!("你的宽是:{}, 你的长是:{}, 你的面积是:{}", cfx.width, cfx.height, cfx.width * cfx.height);

  
}

方法 / 关联函数

方法

方法的概念和其他 OOP 语言一致。第一个参数永远是 self。

struct Rectangle{
    width: u32,
    height: u32,   
}

impl  Rectangle{  // 实现代码块 给 Rectangle 实现一个 get_area 类
    fn get_area(&self) -> u32{ // 方法的第一个参数是 self 只带的是这个Rect结构的应用
        return self.width * self.height
    }
}

fn main(){
    let rect = Rectangle{
        width: 20,
        height: 15
    };

    print!("{}", rect.get_area());

}

关联函数

关联函数就是一种静态方法的表示 他也是在 impl 作用域 中进行实现然而他的第一个形参可以不用指定一个 self.

struct Rectangle {
    width: i32,
    height: i32,
}

impl Rectangle {
    /**
     * 获取该矩阵的面积
     */
    fn get_area(&mut self) -> i32 { 同上 }

    /**
     * [static]
     * 获取一个指定长宽的矩阵
     */
    fn get_rect(width: i32, height: i32) -> Rectangle {
        Rectangle { width, height }
    }
}

fn main() {
    let mut rect = Rectangle::get_rect(20,40);
    println!("{}", rect.get_area());
    rect.width = 20;
    println!("{},{}", rect.height, rect.width)
}

Struct 的 impl 允许存在多个

img

📚 枚举

创建时间:2023-03-30 20:34 星期四


给你个代码 细细品味:

use std::f32::consts::E;

struct QQUser {
    status: QQStatus,
    username: String,
}

impl QQUser {
    /**
     * 创建一个用户
     */
    fn create_user(username: String) -> QQUser {
        QQUser {
            status: QQStatus::Logined,
            username,
        }
    }
}

enum QQStatus {
    // QQ 的几种状态
    Logined,
    UnLogined,
    Hiding,
}

fn send_msg_to_qq(from: QQUser, to: QQUser, mes: String) -> bool {
    let ret = match from.status {
        QQStatus::UnLogined => {
            println!("你还没有登录!");
            false
        }
        QQStatus::Logined => { 
            println!("{} 正在发送消息...", from.username);
            match to.status {
                QQStatus::Logined =>{ 
                    print!("消息发送出去了!");
                    return true;
                },
                _ => {
                    println!("对面似乎不在家..");
                    return false;
                }
            }
        }
        _ => { // 当自己处于登录和非登录的状态是 什么都不会做
            false
        }
    };
    ret
}

fn main() {
    let mut user_a = QQUser::create_user(String::from("张三"));
    let mut user_b = QQUser::create_user(String::from("李四"));
  
    user_b.status = QQStatus::UnLogined;

    send_msg_to_qq(user_a, user_b, String::from("在吗 亲爱的"));
}

我们可以给枚举的值设置不同的数据类型:

image

rust 的 枚举也可以设置方法和关联函数 与 结构一致我们就不说了

Options

在 rust 中没有明确的 null 值,因为 null 是不安全的, 但是 Null 的概念还是有的,也就是某个类型下的缺失值 在 Rust 中我们使用 Options 的 None 进行设置.

fn main() {
    let null: Option<i32> = None;
    let number = match null {
        Option::None => 1,
        Option::Some(number) => number + 3,
    };
}

为什么要这么做

因为有些时候空指针异常的问题很严重为了解决有些时候忘记验证空指针的问题我们可以使用 Options 来进行验证

img

📚 match / iflet

创建时间:2023-03-30 21:33 星期四


match

match name {
	value1 => 1,
	value2 => 2,
	value3 => 3,
}

如果说某些枚举带有些值你可以看看 Options 的使用

if let

我们知道 match 需要枚举全部的可能性才可以 但是当我们值对一种枚举值进行匹配处理的时候用 match 似乎太麻烦了,所以我们可以使用 iflet 来进行优化。

image

我们可以简写成: 这里的3我在代码中定义为了number

fn main() {
    let num : Option<i32> = Some(24);

    if let Option::Some(mut number) = num {
        number += 1;
        println!("{}", number);
    } else {
        println!()
    }
}

  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...