首页 > 其他分享 >【Rust自学】5.2. struct使用例(加打印调试信息)

【Rust自学】5.2. struct使用例(加打印调试信息)

时间:2024-12-30 10:29:10浏览次数:3  
标签:5.2 struct rectangle width length 调试信息 u32 Debug Rectangle

对不起我都写到第8章了才发现我忘记发这一篇了,现在补上,不过这可能导致专栏的文章顺序有一点问题,但也只能将就着了。

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)

5.2.1. 例子需求

创建一个函数,计算长方形的面积,长和宽类型均为u32且面积类型为u32

5.2.2. 普通解法

最简单的解法就是定义这个函数有两个参数:一个长一个宽,都为&u32类型(例子中说了是u32类型,并且这个场景下不需要函数获得数据所有权,所以使用引用在数据类型前加&),在函数中返回长乘以宽的值就行。

fn main() {  
    let width = 30;  
    let length = 50;  
    println!("{}", area(&width, &length));  
}  
  
fn area(width: &u32, length: &u32) -> u32 {  
    width * length  
}

输出:

1500

5.2.3. 元组解法

普通解法本身没有问题,但在可维护性有一个问题:长和宽是独立的参数,程序中的任何地方都不清楚这些参数是相关的。将宽度和高度组合在一起会更具可读性和更易于管理。对于数据的整合,使用元组再好不过(因为都是同一数据类型,所以在这里使用数组也是可以的)。

fn main() {  
    let rectangle = (30,50);  
    println!("{}", area(&rectangle));  
}  
  
fn area(dim:&(u32,u32)) -> u32 {  
    dim.0 * dim.1  
}

输出:

1500

5.2.4. struct解法

元组解法虽然提升了可维护性,但代码的可读性变差了,因为如果不加注释没人知道元组的第一个数据是代表长还是代表宽(虽然对于计算面积来说无所谓,但是对于较大的项目来说很重要)。元组的元素是没有名字的,即使是元组结构体(上一篇文章中有讲),它里面的元素也是没有名字的。

那么那种数据结构可以把两个数据整合到一起并且分别赋名呢?没错,就是struct。

struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
fn main() {  
    let rectangle = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    println!("{}", area(&rectangle));  
}  
  
fn area(dim:&Rectangle) -> u32 {  
    dim.width * dim.length  
}

5.2.5.打印结构体的调试信息

接着上面的代码,如果再加一行直接打印rectangle这个实例会怎么样呢?代码如下:

struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
fn main() {  
    let rectangle = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    println!("{}", area(&rectangle));  
    println!("{}", rectangle);  //直接打印实例
}  
  
fn area(dim:&Rectangle) -> u32 {  
    dim.width * dim.length  
}

输出:

error[E0277]: `Rectangle` doesn't implement `std::fmt::Display`
  --> src/main.rs:12:20
   |
12 |     println!("{}", rectangle);
   |                    ^^^^^^^^^ `Rectangle` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `Rectangle`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

先解释一下报错:println!这个宏它可以执行很多格式化的打印。占位符{}就是告诉println!来使用std::fmt::Display这个trait(理解成接口),类似于Python的toString,而在报错信息中提到的就是Rectangle并没有实现std::fmt::Display这个trait,也就不能打印。

实际上,目前所讲的基础数据类型,默认都实现了std::fmt::Display这个trait,因为它们的展示方式都比较单一,比如说把1打印出来,那程序只可能打印出阿拉伯数字1。但是对于Rectangle,它里面有2个字段,是要都打印,还是打印width,还是打印length呢?可能性太多了,所以Rust并没有为struct默认实现std::fmt::Display这个trait。

但如果我们继续往下看到这一行:

= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

编译器提示我们可以使用{:?}或者是{:#?}来代替{}。那就试试第一种:

struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
fn main() {  
    let rectangle = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    println!("{}", area(&rectangle));  
    println!("{:?}", rectangle);  //把`{}`改为`{:?}`
}  
  
fn area(dim:&Rectangle) -> u32 {  
    dim.width * dim.length  
}

还是报错了:

error[E0277]: `Rectangle` doesn't implement `Debug`
  --> src/main.rs:12:22
   |
12 |     println!("{:?}", rectangle);
   |                      ^^^^^^^^^ `Rectangle` cannot be formatted using `{:?}`
   |
   = help: the trait `Debug` is not implemented for `Rectangle`
   = note: add `#[derive(Debug)]` to `Rectangle` or manually `impl Debug for Rectangle`
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Rectangle` with `#[derive(Debug)]`
   |
1  + #[derive(Debug)]
2  | struct Rectangle {
   |

但报错信息变了,上一回是没有实现std::fmt::Display,这回是没有实现DebugDebugDisplay一样也是一种格式化方法。继续往下看到note这行:

= note: add `#[derive(Debug)]` to `Rectangle` or manually `impl Debug for Rectangle`

编译提示我们添加#[derive(Debug)]到代码中或是手动实现Debug这个trait。这里使用前一种(后一种下一篇文章会讲):

#[derive(Debug)]  
struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
fn main() {  
    let rectangle = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    println!("{}", area(&rectangle));  
    println!("{:?}", rectangle);  
}  
  
fn area(dim:&Rectangle) -> u32 {  
    dim.width * dim.length  
}

输出:

1500
Rectangle { width: 30, length: 50 }

这次就可以成功通过了。Rust本身包含了打印调试信息的功能(也就是debug信息的功能),但必须为自己代码中的结构体显式地选择这一功能,所以要在定义结构体前加上#[derive(Debug)]这个注解。这种输出把结构体的名字、字段的名字及值都显示出来了。

有的时候结构体里有很多的字段,这时候{:?}说打印出的横向排列的字段就没有那么易读。如果想要输出更加易读,那就把{:?}改为{:#?}

#[derive(Debug)]  
struct Rectangle {  
    width: u32,  
    length: u32,  
}  
  
fn main() {  
    let rectangle = Rectangle{  
        width: 30,  
        length: 50,  
    };  
    println!("{}", area(&rectangle));  
    println!("{:#?}", rectangle);  
}  
  
fn area(dim:&Rectangle) -> u32 {  
    dim.width * dim.length  
}

输出:

1500
Rectangle {
    width: 30,
    length: 50,
}

这个输出中字段就是纵向排列,对于有很多字段的结构体来说更加易读。

实际上Rust提供了很多trait让我们可以进行derive(派生),这些trait可以为自定义类型添加很多功能。所有的trait和它们的行为都可以在官方指南中找到,我把网址链接附在这里

在上边的代码中就是让Rectangle这个struct派生于Debug这个trait,所以在打印时就可以使用调试模式。

再举个例子,假设你有一个表示点坐标的结构体:

#[derive(Debug, Clone, PartialEq)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point1 = Point { x: 1, y: 2 };
    let point2 = point1.clone();
    println!("{:?}", point1); // 使用 Debug 特质打印 Point
    assert_eq!(point1, point2); // 使用 PartialEq 特质比较两个 Point
}

在这个例子中:

  • #[derive(Debug)]允许你使用{:?}格式化规范来打印Point结构体的实例。
  • #[derive(Clone)]允许你创建一个Point实例的副本。
  • #[derive(PartialEq)]允许你比较两个Point实例是否相等。

标签:5.2,struct,rectangle,width,length,调试信息,u32,Debug,Rectangle
From: https://blog.csdn.net/weixin_71793197/article/details/144814530

相关文章

  • CIV6782 Climate resilient water infrastructure
    CIV6782Climateresilientwaterinfrastructuredesign–CourseworkbriefDrCharlesRougé(c.rouge@sheffield.ac.uk)Part1–Documentanalysis(35marks)Pleasepickoneofthefollowingthreeresearchpapers:Quinnetal.(2018).Exploringhowchanging......
  • 如何解决系统升级到 macOS 15.2 Sequoia 后 Siri 无法语音回复问题 All In One
    如何解决系统升级到macOS15.2Sequoia后Siri无法语音回复问题AllInOneAppleMBPsolutionSiriResponsesVoicefeedbackdemos(......
  • VbaCompiler 2.5.2 版本 分析
    VbaCompiler2.5.2版本目录VbaCompiler2.5.2版本excel调试(关注生成的xxxx_xlsm_32.dll)SetThisWorkbooksub_67B82BF1check_md5_67B82421get_embedded_md5_67B815A3md5校验(关注生成的xxxx_xlsm_32.dll)签名校验(关注释放到temp目录的cbinrtl.dll)rkey校验key3校验py测试关联Vb......
  • Ubuntu20.04安装Qt5.15.2并配置qml_ros_plugin插件
    安装QtQt老版本采用离线安装,新版本采用在线安装器安装,在官网安装速度很慢,一般在国内的源下载。在中科大源下载Qt在线安装器http://mirrors.ustc.edu.cn/qtproject/official_releases/online_installers/安装依赖sudoaptinstallgccg++makecmakebuild-essentiallibgl1-......
  • Structured-Streaming初识
    一、概览StructuredStreaming是一个基于SparkSQL引擎构建的可扩展且容错的流处理引擎。可以像在静态数据上表达批量计算一样表达流计算。SparkSQL引擎将负责以增量方式连续运行它,并在流数据继续到达时更新最终结果。可以使用Scala、Java、Python或R中的Dataset/DataFrameAPI......
  • 【思维导图系列】Simple instructions: Source code quality defined in ISO26262
    MainstandardsregaringtheSWdesignandqualityassurance1).MISRACprogrammingrulesforembeddedcriticalsustems[MISRA-C:2004];2).HISsourcecodeMetricsforsoftwareevaluations[HIS];3).ASPICEforsoftwareprocessabdmanagement[ISO/IEC15504......
  • 论文阅读:Deep Fusion Clustering Network With Reliable Structure Preservation
    论文地址:DeepFusionClusteringNetworkWithReliableStructurePreservation|IEEEJournals&Magazine|IEEEXplore代码地址:https://github.com/gongleii/DFCN-RSP摘要深度聚类通过优雅地利用数据表示来寻找样本的划分,已引起广泛关注。最近,将自编码器(AE)与图神经......
  • Diamonds task instructions
    Assessmenttask2Outcomescovered2and3AssessmenttaskinstructionsThisisanopen-bookprojectcoveringOutcomes2and3.Theprojectisbrokendownintotwostages.Stage1istheprogramimplementationandStage2isthetestingofthecompletedpro......
  • 使用UnstructuredRSTLoader加载RST文件的实战指南
    在大数据时代,爬取和收集网络数据是AI应用中的重要一环。而今天要跟大家分享的是一个非常强大的工具——Spider,它以其快速和高性价比著称,非常适合用于获取适合大型语言模型(LLM)的数据。技术背景介绍Spider是一款专门为AI代理和大型语言模型设计的网络爬虫工具。它最大的特......
  • CS61B srping 2018 lab03 https://sp18.datastructur.es/
    UnitTestingwithJUnit,Debugging准备装好CS61B插件(emmmmm,不装也没事)把lab2的IntList.java复制到lab3/IntList文件夹.看看关于测试的课程视频介绍啊?JUnit是java测试框架,现在要用JUnit进行单元测试,单元Unit就是把程序分成小块的单元,一个单元的功能尽量少,单独测试,......