rust学习-打印结构体中的vec

write! 宏

将格式化后的数据写入到一个缓冲区(buffer),而不是直接打印到标准输出或文件中。

这个缓冲区可以是字符串,也可以是需要写入的文件的缓冲区。

rust 复制代码
write!(writer, format_string, expr1, expr2, ...);

writer 参数是一个实现了 std::io::Write trait 的对象,表示要将数据写入到哪里。

format_string 是一个格式化字符串,可以包含占位符 {},表示后面要插入的值。 expr1、expr2 等是值的表达式,可以是变量,常量,函数等。

write! 宏不会自动添加末尾的换行符。如果需要在写入缓冲区后添加换行符,可以在格式化字符串末尾添加 "\n"。

rust 复制代码
use std::io::Write;

fn main() {
    let mut buffer = Vec::new(); // 创建一个空的缓冲区

    let n = 123;
    // 使用 write! 宏将格式化字符串 n = {}\n 写入到一个空的缓冲区 buffer 中
    // 使用 unwrap() 方法处理写入缓冲区时可能出现的错误
    write!(&mut buffer, "n = {}\n", n).unwrap();

	// 使用 String::from_utf8_lossy() 方法将缓冲区的内容转换为字符串格式,并进行输出
    println!("{}", String::from_utf8_lossy(&buffer));
}

// 打印内容
// n = 123
// \n

write! 宏的返回值是一个 std::io::Result<()> 类型的值,表示写入操作是否成功。

  • 执行成功时,它返回一个包含 () 值的 Ok 枚举成员
  • 执行失败时,它会返回一个包含错误信息的 Err 枚举成员
rust 复制代码
use std::io::Write;

fn main() {
	// 创建一个缓冲区
    let mut buffer = Vec::new();
    let n = 123;
    
     // 调用 write! 宏写入数据
    let result = write!(&mut buffer, "n = {}\n", n);

    if result.is_err() {
    	// unwrap_err 只能在err的时候使用
        println!("Error: {}", result.unwrap_err());
    } else {
        println!("Write succeed.");
        println!("{:?}", buffer);
    }
}

// 打印
// Write succeed.
// [110, 32, 61, 32, 49, 50, 51, 10]
  • 如果发现错误,使用 unwrap_err() 方法获取错误信息并进行输出
  • 如果没有出现错误,输出信息 "Write succeed."。

打印结构体中的vec

rust 复制代码
use std::fmt; // 导入 `fmt` 模块。

// 定义一个包含单个 `Vec` 的结构体 `List`。
struct List(Vec<i32>);

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 使用元组的下标获取值,并创建一个 `vec` 的引用
        // 创建一个指向结构体 List 中第一个元素的不可变引用
		// self 是一个 &List 类型的引用,它表示一个指向类型为 List 的结构体实例的引用
		// .0 表示取得 List 结构体中的第一个元素
		// 必须使用 &self.0 来获取 List 这个引用所指向的 Vec<i32> 实例
        let vec = &self.0;

		// ? 运算符,表示在发生错误时返回错误信息
		// 这样在上层函数中可以进行进一步的处理
		// ? 运算符只有在当前函数返回 Result 类型时才能使用
        write!(f, "[")?;

        // 使用 `v` 对 `vec` 进行迭代,并用 `count` 记录迭代次数。
        for (count, v) in vec.iter().enumerate() {
            // 对每个元素(第一个元素除外)加上逗号。
            // 使用 `?` 或 `try!` 来返回错误。
            if count != 0 { write!(f, ", ")?; }
            write!(f, "{}", v)?;
        }

        // 加上配对中括号,并返回一个 fmt::Result 值
        write!(f, "]")
    }
}

fn main() {
    let v = List(vec![1, 2, 3]);
    println!("{}", v);
}

按照 k-v的形式打印

rust 复制代码
use std::fmt; // 导入 `fmt` 模块。

// 定义一个包含单个 `Vec` 的结构体 `List`。
struct List(Vec<i32>);

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 使用元组的下标获取值,并创建一个 `vec` 的引用
        // 创建一个指向结构体 List 中第一个元素的不可变引用
		// self 是一个 &List 类型的引用,它表示一个指向类型为 List 的结构体实例的引用
		// .0 表示取得 List 结构体中的第一个元素
		// 必须使用 &self.0 来获取 List 这个引用所指向的 Vec<i32> 实例
        let vec = &self.0;

		// ? 运算符,表示在发生错误时返回错误信息
		// 这样在上层函数中可以进行进一步的处理
		// ? 运算符只有在当前函数返回 Result 类型时才能使用
        write!(f, "[")?;

        // 使用 `v` 对 `vec` 进行迭代,并用 `count` 记录迭代次数。
        for (count, v) in vec.iter().enumerate() {
            // 对每个元素(第一个元素除外)加上逗号。
            // 使用 `?` 或 `try!` 来返回错误。
            if count != 0 { write!(f, ", ")?; }
            write!(f, "{}: {}", count, v)?;
        }

        // 加上配对中括号,并返回一个 fmt::Result 值
        write!(f, "]")
    }
}

fn main() {
    let v = List(vec![1, 2, 3]);
    println!("{}", v);
}

附录

unwrap 和 unwrap_err

  • unwrap() 方法用于从 Ok 枚举成员中取出存储的值,如果结果是 Err 枚举成员,则会引发 panic
  • unwrap_err() 方法用于从 Err 枚举成员中取出存储的错误信息,如果结果是 Ok 枚举成员,则会引发 panic。该方法主要用于在程序发生错误时对错误信息进行记录和处理,避免程序崩溃

display trait

对于 Vec 或其他任意泛型容器(generic container)

fmt::Display 都没有实现。因此在这些泛型的情况下要用 fmt::Debug。

rust 复制代码
use std::fmt; // 导入 `fmt`

// 带有两个数字的结构体
// 推导出 `Debug`,以便与 `Display` 的输出进行比较
#[derive(Debug)]
struct MinMax(i64, i64);

// 实现 `MinMax` 的 `Display`。
impl fmt::Display for MinMax {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 使用 `self.number` 来表示各个数据。
        write!(f, "({}, {})", self.0, self.1)
    }
}

// 为了比较,定义一个含有具名字段的结构体
#[derive(Debug)]
struct Point2D {
    x: f64,
    y: f64,
}

// 类似地对 `Point2D` 实现 `Display`
impl fmt::Display for Point2D {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 自定义格式,使得仅显示 `x` 和 `y` 的值。
        write!(f, "x: {}, y: {}", self.x, self.y)
    }
}

fn main() {
    let minmax = MinMax(0, 14);

    println!("Compare structures:");
    println!("Display: {}", minmax);
    println!("Debug: {:?}", minmax);

    let big_range =   MinMax(-300, 300);
    let small_range = MinMax(-3, 3);

    println!("The big range is {big} and the small range is {small}", small = small_range, big = big_range);

    let point = Point2D { x: 3.3, y: 7.2 };
    println!("Compare points:");
    println!("Display: {}", point);
    println!("Debug: {:?}", point);

    // 报错。`Debug` 和 `Display` 都被实现了,但 `{:b}` 需要 `fmt::Binary`
    // 得到实现。这语句不能运行。
    // println!("What does Point2D look like in binary: {:b}?", point);
}
相关推荐
我的心永远是冰冰哒17 分钟前
ad.concat()学习
学习
ZZZ_O^O22 分钟前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
slomay2 小时前
关于对比学习(简单整理
经验分享·深度学习·学习·机器学习
hengzhepa2 小时前
ElasticSearch备考 -- Async search
大数据·学习·elasticsearch·搜索引擎·es
小小洋洋4 小时前
BLE MESH学习1-基于沁恒CH582学习
学习
Ace'5 小时前
每日一题&&学习笔记
笔记·学习
IM_DALLA5 小时前
【Verilog学习日常】—牛客网刷题—Verilog进阶挑战—VL25
学习·fpga开发·verilog学习
丶Darling.5 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树
姜学迁7 小时前
Rust-枚举
开发语言·后端·rust
z樾7 小时前
Github界面学习
学习