在 Rust 中为 List 实现 fmt::Display

RustRustBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在这个实验中,我们要为 Rust 中一个名为 List 的结构体实现 fmt::Display 特性,该结构体包含一个 Vec。挑战在于使用 write! 宏按顺序处理每个元素,因为它会生成一个 fmt::Result,需要对其进行正确处理。为了解决这个问题,我们可以使用 ? 运算符检查 write! 是否返回错误,如果返回错误则返回该错误,否则继续执行。通过为 List 实现 fmt::Display,我们可以遍历向量中的元素,并在方括号内打印它们,元素之间用逗号分隔。任务是修改程序,使其还能打印向量中每个元素的索引。修改后的预期输出是 [0: 1, 1: 2, 2: 3]

注意:如果实验未指定文件名,你可以使用任何你想要的文件名。例如,你可以使用 main.rs,通过 rustc main.rs &&./main 进行编译和运行。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/traits("Traits") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99189{{"在 Rust 中为 List 实现 fmt::Display"}} rust/integer_types -.-> lab-99189{{"在 Rust 中为 List 实现 fmt::Display"}} rust/function_syntax -.-> lab-99189{{"在 Rust 中为 List 实现 fmt::Display"}} rust/expressions_statements -.-> lab-99189{{"在 Rust 中为 List 实现 fmt::Display"}} rust/method_syntax -.-> lab-99189{{"在 Rust 中为 List 实现 fmt::Display"}} rust/traits -.-> lab-99189{{"在 Rust 中为 List 实现 fmt::Display"}} rust/operator_overloading -.-> lab-99189{{"在 Rust 中为 List 实现 fmt::Display"}} end

测试用例:List

为一个其元素必须按顺序逐个处理的结构体实现 fmt::Display 特性是很棘手的。问题在于每个 write! 都会生成一个 fmt::Result。要正确处理这个问题,就需要处理所有的结果。Rust 为此提供了 ? 运算符。

write! 上使用 ? 看起来是这样的:

// 尝试使用 `write!` 看看是否出错。如果出错,返回
// 错误。否则继续。
write!(f, "{}", value)?;

有了 ? 之后,为 Vec 实现 fmt::Display 就很简单了:

use std::fmt; // 导入 `fmt` 模块。

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

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 使用元组索引提取值,
        // 并创建一个指向 `vec` 的引用。
        let vec = &self.0;

        write!(f, "[")?;

        // 遍历 `vec` 中的 `v`,同时枚举迭代计数 `count`。
        for (count, v) in vec.iter().enumerate() {
            // 对于除第一个元素之外的每个元素,添加一个逗号。
            // 使用 `?` 运算符在出错时返回。
            if count!= 0 { write!(f, ", ")?; }
            write!(f, "{}", v)?;
        }

        // 关闭打开的方括号并返回一个 `fmt::Result` 值。
        write!(f, "]")
    }
}

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

活动

尝试修改程序,使其还能打印向量中每个元素的索引。新的输出应该是这样的:

[0: 1, 1: 2, 2: 3]

总结

恭喜你!你已经完成了“测试用例:List”实验。你可以在 LabEx 中练习更多实验来提升你的技能。