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);
}
相关推荐
DongLi011 天前
rustlings 学习笔记 -- exercises/05_vecs
rust
西岸行者2 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意2 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
番茄灭世神2 天前
Rust学习笔记第2篇
rust·编程语言
别催小唐敲代码2 天前
嵌入式学习路线
学习
毛小茛2 天前
计算机系统概论——校验码
学习
babe小鑫2 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms2 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下2 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。2 天前
2026.2.25监控学习
学习