前言#
昨天我们学了struct的概念,今天我们继续往下学
加强struct概念#
昨天我们学了struct,今天我们来加强下,毕竟这个数据结构将来会有非常多的地方用到。
计算矩形面积#
一个很简单的小栗子
fn main () {
let wid = 10;
let hei = 12;
let result = area(&wid, &hei);
println!("{result}");
}
fn area (wid: &u32, hei: &u32) -> u32 {
wid * hei
}
计算结果也正常,但是我们可以优化下。
现在的代码中,宽和高并没有关联。对于一个矩形来说,宽和高都是它的属性,所以把他们放在一起是一种好的思想约束。
那怎么放到一起呢?第一想法自然是数组或者元组。但是用数组明显不太适合,所以我们来试下元组。
fn main () {
let rect = (10, 12);
let result = area(&rect);
println!("{result}");
}
fn area (rect: &(u32, u32)) -> u32 {
rect.0 * rect.1
}现在宽和高有关联啦,但是你是否发现了个问题,那就是rect.0和rect.1是啥?第一眼压根看不出是啥,并且如果宽和高还有其他用处,这里就会有可能导致错用。
那该如何处理呢?你应该已经想到了,元组还有一种获取元素的方式--解构。我们来改下代码
fn main () {
let rect = (10, 12);
let result = area(&rect);
println!("{result}");
}
fn area ((wid, hei): &(u32, u32)) -> u32 {
wid * hei
}这样就不会有误导了。
这是很好,但是如果这里还有其他字段呢?比如矩形的名字,这是一个字符串,那就完全不适用了。所以对于这种需要拓展的场景来说,元组并不是一个好的方案。而且你也不能总是解构,万一参数巨多呢?
所以这里就需要能通过name匹配的,能容纳多种类型的数据结构。
那自然就是我们的struct结构体。
让我们来改下代码
struct Rect {
width: f64,
height: f64,
}
fn main () {
let rect = Rect {
width: 10.0,
height: 12.0,
};
let result = area(&rect);
println!("{result}");
}
fn area (rect: &Rect) -> f64 {
rect.width * rect.height
}如何打印struct#
我们先来看下一个报错

这个报错的大致意思是Rect这个struct内部没有实现std里的fmt里的Display这个trait。
对于struct这种不确定结构来说,rust的println!是不知道怎么打印的,而标量类型、元组、数组字符串这些确定的结构则内部实现了
那么咋办呢?其实上面的报错没有截全

这是在提示我们用{:?}或者{:#?}去做打印,我们来试下

换了个报错,说是没有实现Debug这个trait。。。。但是它又给了我们一个提示

我们再来试下

果然没有报错了,来下打印结果

除了这种方式之外还有一种方式,使用dbg!这个宏macro。和println!这个macro不同,dbg!传入的是表达式的所有权。
另外如果这个表达式可以算出值,那么这个表达式的结果也会被打印出来,我们来试下。
fn main () {
let rect = Rect {
width: 10.0,
height: 12.0,
};
dbg!(rect.width * rect.height);
dbg!(rect);
}
另外dbg!会返回值的所有权
fn main () {
let rect = Rect {
width: 10.0,
height: 12.0,
};
let value = dbg!(rect.width * rect.height);
println!("{value}");
dbg!(rect);
} 
另外如果我们不想传入表达式的所有权,这也是可以的,只要传入引用即可。
dbg!(&rect);总结#
今天我们用一个计算矩形面积的小栗子来加深对struct结构体的印象,还知道了如何打印结构体。
参考#
- ^rust-example-calc-square https://doc.rust-lang.org/stable/book/ch05-02-example-structs.html#an-example-program-using-structs
发布于 2022-12-05 21:49・IP 属地广东
