rust学习六、简单的struct结构

ops/2025/2/21 8:28:13/

一、结构定义
struct-翻译为结构/结构体

总体上有两种定义方式:带有详细属性名的;不带属性名(元组)

从工程角度出发,并不推荐不带属性的定义方式,因为不友好。希望rust后面不要搞类似好像很友好,但是其实起到干扰作用的语法。

如果再考虑到一些rust的其它问题,定义一个结构其实也不是那么容易。

示例:
struct Point{x:f64,y:f64}
struct Triangle(Point,Point,Point);

/**
 * 家庭结构体s
 */
struct Family {
    name: String,
    father: String,
    mather: String,
    children: Vec<String>,
}
/**
 * 这都什么狗屎语法。
 */
struct Book<'a> {
    name: &'a str,
    author: &'a str,
    price: f64,
    pubyear: i32,
}
fn main() {
    let mut family = Family {
        name: String::from("家"),
        father: String::from("爸爸"),
        mather: String::from("妈妈"),
        children: vec![],
    };

    family.children.push(String::from("老大-独龙"));
    family.children.push(String::from("老二-独眼"));
    family.children.push(String::from("老三-独秀"));
    family.children.push(String::from("老四-嘟嘟"));
    family.children.push(String::from("老五-杜牧"));

    //打印家庭结构体
    println!(
        "家庭:{},父亲:{},母亲:{}",
        family.name, family.father, family.mather
    );
    for child in &family.children {
        println!("孩子:{}", child);
    }
    let mut 三国演义 = Book {
        name: "三国演义",
        author: "罗贯中",
        price: 29.8,
        pubyear: 1300,
    };
    
    //各种创建结构实例的方式
    // 方式一:双点号复制
    let mut 红楼梦=Book{
        name:"红楼梦",
        author:"曹雪芹",
        ..三国演义
    };
    //方式二: 略属性名
    let 西游记=write_book("西游记","吴承恩",24.0,1525);
    //方式三:使用基于元组定义的。 比java的record还简单

    let books=[三国演义,红楼梦,西游记];
    for i in 0..books.len() {
        print_book(&books[i]);
    }
    let p1=Point{x:10.0,y:20.0};
    let p2=Point{x:20.0,y:20.0};
    let p3=Point{x:20.0,y:10.0};
    let t=Triangle(p1,p2,p3);
    print_triangle(&t);
}

fn print_book(book:&Book){
    println!(
        "书名:{},作者:{},价格:{},出版年:{}",
        book.name, book.author, book.price, book.pubyear
    );
}

fn print_triangle(t:&Triangle){
    println!("三点坐标:");
    println!("{},{}",t.0.x,t.0.y);
    println!("{},{}",t.1.x,t.1.y);
    println!("{},{}",t.2.x,t.2.y);
}

fn write_book<'a>(name:&'a str,author:&'a str,price:f64,pubyear:i32)->Book<'a>{
    Book{
        name,
        author,
        price,
        pubyear
    }
}

在上例中,结构Book使用了非常奇怪的语法:


struct Book<'a> {

    name: &'a str,

    author: &'a str,

    price: f64,

    pubyear: i32,

}

这个能够定义出来,是因为编译器提示的。

作为初学者,先绕过这个吧。 

rust结构体实例的属性赋值也有两种方式:
属性逐一赋值

双点号复制属性值
例如以下就是:
let mut 红楼梦=Book{
        name:"红楼梦",
        author:"曹雪芹",
        ..三国演义
    };

二、几种打印方式
至少有4种打印方式:

逐一访问属性名
println!使用宏符号:?
println!使用宏符号:#?
使用dbg!
后面三种方式,要求定义结构的时候,在结构前添加

#[derive(Debug)]
这个东西应该怎么称呼了? "属性"还是"编译指示符"?,有点乱七八杂的。 

从宏观上而言,很多类似的都是可以称为编译指示符,所以为了更加精准一些,我愿意称为"功能编译指示"。

通过这个功能编译指示,rust编译器会自动实现特定功能。

示例:


#[derive(Debug)]
struct Family{
    father:String,
    mather:String,
    address:String
}

fn main(){
    let mut mf=Family{
        father:String::from("lu"),
        mather:String::from("hu"),
        address:String::from("中国")
    };
    println!("我家-{},{},{}",mf.father,mf.mather,mf.address);
    print_family(&mf);
    print_family_use_dbg(&mf);
}

fn print_family(f:&Family){
    //你不能直接打印,否则会有奇奇怪怪的错误提示
    //println!("{}",f);  // 这个会提示错误,所以注释掉了

    //使用奇怪符号 :?打印结构体
    println!("我家:?-{:?}",f);

    //使用奇怪的符号,可以打印结构体 :#?
    println!("我家:#?-{:#?}",f);
}

fn print_family_use_dbg(f:&Family){
    dbg!(f);
}

三、定义结构内的函数
在没有看书本正文之前,我以为和java的record一样,在struct内部定义函数。

其实不是! 如果要为结构体定义函数,必须在结构体外。 不知道为什么要那样? 难道内部定义的话,有其它用途?

示例:
#[derive(Debug)]
struct Cube{
    length: u32,
    width: u32,
    height: u32,
}
impl Cube{
    fn volume(&self) -> u32{
        return self.length * self.width * self.height;
    }
    fn is_bigger_than(&self, other: &Cube) -> bool{
        return self.volume() > other.volume();
    }

}

fn main() {
    let cube = Cube{length: 10, width: 12, height: 25};
    let cube2 = Cube{length: 15, width: 10, height: 30};
    println!("立方体的体积={}立方厘米",cube.volume());
    let is_bigger = cube.is_bigger_than(&cube2);
    match is_bigger{
        true => println!("cube的体积{}大于cube2体积{}",cube.volume(), cube2.volume()),
        false =>println!("cube的体积{}小于cube2体积{}",cube.volume(), cube2.volume()),
    };
}

结构体的函数有几个特点:

在结构体外,使用impl xxxx {}的方式,其中xxx是结构体名称
在一个impl xxx{}结构中,可以定义多个函数
书本建议我们:函数的第一个方法总是 &self,这点和python有点类似
参数&self虽然有定义,但是调用的时候不需要显示传递,因为这是编译器实现的

四、一点小补充
4.1定义没有成员的结构
在很多OOP,允许我们定义没有成员的对象。

我们可以把struct大体当做对象。

rust中也可以定义没有成员的结构,例如:

#[derive(Debug)]
struct NoItem; 
struct NoItem2();

let nod=NoItem{};
println!("空结构体:{:?}",nod);
 

rust允许这样做,是因为struct这个类型具有很多作用,即使它不用于存储数据,也有很多作用。具体什么作用,只能等待深入后了解。

总之在rust中,绝大部分复杂的类型,都是基于结构定义的。

4.2struct大有作用
前有言:某种程度上可以把struct视为OOP中的对象

虽然rust不是明面上的OOP,但还是吸收了很多OOP的营养。

总之,许多复杂类型都是基于结构定义的。具体不一一罗列。

五、小结
结构体无疑是一个有用的东西,它就算垃圾袋/宝物袋一样,什么都可以往里装,大大方便了工程师!

  

          关注灵活就业新业态,关注公账号:贤才宝


http://www.ppmy.cn/ops/160191.html

相关文章

汉化VScode

第一步 打开开发工具, 点扩展按钮 第二步 在输入框内输入Chinese 第三步 点击(Chinese)中文插件 第四步 点击 install(安装) 安装好后, 关掉开发工具, 重新打开, 就汉化成功了 .

《DAMA数据管理知识体系指南》第一章 数据管理读书笔记

《DAMA数据管理知识体系指南》第一章 数据管理读书笔记 《DAMA数据管理知识体系指南》第一章围绕数据管理展开多方面论述,涵盖DAMA与DMBOK概述、数据管理基础概念、原则、挑战、战略及框架等内容,为数据管理专业人员提供全面指导,对理解和实践数据管理意义重大。 一、DAMA…

洛谷 P10726 [GESP202406 八级] 空间跳跃 C++ 完整题解

一、题目链接 P10726 [GESP202406 八级] 空间跳跃 - 洛谷 二、解题思路 我们要对输入的挡板进行排序&#xff0c;按高度从高到低&#xff08;从小到大&#xff09;。 排序之后s和t都要更新。 struct Baffle {int l, r;int h;int id; } b[1005];void Sort() {sort(b 1, b 1 n…

本地部署MindSearch(开源 AI 搜索引擎框架),然后上传到 hugging face的Spaces——L2G6

部署MindSearch到 hugging face Spaces上——L2G6 任务1 在 官方的MindSearch页面 复制Spaces应用到自己的Spaces下&#xff0c;Space 名称中需要包含 MindSearch 关键词&#xff0c;请在必要的步骤以及成功的对话测试结果当中 实现过程如下&#xff1a; 2.1 MindSearch 简…

qt:常见标签操作,倒计时功能,进度条与日历

1.标签常见函数 函数功能void setext(const QString &text)设置文本QString text()const获取文本void setPixmap(const QPixmap)与Pixmap()const设置和获取图像void setAlignment(Qt::Alignment alignment)设置对齐&#xff08;获取和上面一样&#xff09;void setWordWr…

DeepSeek+kimi自动生成ppt

AI自动生成ppt 描述需求&#xff0c;生成大纲 在deepseek里输入需求&#xff0c;https://chat.deepseek.com/&#xff0c; 或者在其它AI搜索里&#xff0c;如kimi中Kimi.ai - 会推理解析&#xff0c;能深度思考的AI助手 搜索后会得到大纲&#xff0c;复制出来。 打开KIMI …

【HarmonyOS Next】鸿蒙监听手机按键

【HarmonyOS Next】鸿蒙监听手机按键 一、前言 应用开发中我们会遇到监听用户实体按键&#xff0c;或者扩展按键的需求。亦或者是在某些场景下&#xff0c;禁止用户按下某些按键的业务需求。 这两种需求&#xff0c;鸿蒙都提供了对应的监听事件进行处理。 onKeyEvent 默认的…

当滑动组件连续触发回调函数的三种解决办法

1. 节流&#xff08;Throttle&#xff09; 节流是一种限制函数调用频率的技术&#xff0c;它会在一定时间内只允许函数执行一次。在滑动组件中使用节流可以避免短时间内的连续触发。 Entry Component struct ThrottleSlideExample {// 节流时间间隔&#xff0c;单位为毫秒pri…