有没有一种方法可以打印枚举值?

75

有没有一种简单的方法来格式化和打印枚举值?我以为它们会有一个默认的实现std::fmt::Display,但是似乎并不是这样。

enum Suit {
    Heart,
    Diamond,
    Spade,
    Club
}

fn main() {
    let s: Suit = Suit::Heart;
    println!("{}", s);
}
期望输出: 错误:
error[E0277]: the trait bound `Suit: std::fmt::Display` is not satisfied
  --> src/main.rs:10:20
   |
10 |     println!("{}", s);
   |                    ^ the trait `std::fmt::Display` is not implemented for `Suit`
   |
   = note: `Suit` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
   = note: required by `std::fmt::Display::fmt`

1
我为这个确切的问题编写了一个crate:https://crates.io/crates/enum-display - SeedyROM
5个回答

93

Debug 特性打印出 Enum 变量的名称。

如果您需要格式化输出,可以像这样为您的 Enum 实现 Display

use std::fmt;

enum Suit {
    Heart,
    Diamond,
    Spade,
    Club
}

impl fmt::Display for Suit {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       match self {
           Suit::Heart => write!(f, "♥"),
           Suit::Diamond => write!(f, "♦"),
           Suit::Spade => write!(f, "♠"),
           Suit::Club => write!(f, "♣"),
       }
    }
}

fn main() {
    let heart = Suit::Heart;
    println!("{}", heart);
}

为什么当我尝试像这样写的时候,它总是打印第一个心形 => write!(f, "♥") 钻石 => write!(f, "♦") - wonderflow
要打印出 ♦,您需要创建对 Suit::Diamond 的引用,然后将其打印出来。例如 let diamond = Suit::Diamond; println!("{}", diamond); - Matilda Smeds
1
在你的回答中,解除引用 self 有什么必要? - Trí Phan
很好的发现,它不是必需的! - Matilda Smeds

92

您可以推导出实现std::format::Debug

#[derive(Debug)]
enum Suit {
    Heart,
    Diamond,
    Spade,
    Club
}

fn main() {
    let s = Suit::Heart;
    println!("{:?}", s);
}

由于Display旨在向人类显示,而编译器无法自动决定哪种样式是合适的,因此不可能推导出DisplayDebug旨在为程序员提供服务,因此可以自动生成一个内部暴露视图。


28
这不是答案。 - Clemens Tolboom
4
OP要求“一个简单的方法来格式化和打印枚举值”。这是所有答案中最简单的,它格式化并打印出来了。对于OP来说,答案是正确的。 - Bryan Larsen

27

如果您想为枚举变量自动生成Display实现,您可能需要使用strum crate:

#[derive(strum_macros::Display)]
enum Suit {
    Heart,
    Diamond,
    Spade,
    Club,
}

fn main() {
    let s: Suit = Suit::Heart;
    println!("{}", s); // Prints "Heart"
}

4
虽然它目前没有很多票数,但这可能是您想要的,因为它是提供任何枚举类型简单显示支持所需工作最少的选项。 - optevo

7

结合DK.Matilda Smeds的答案,得到稍微更简洁的版本:

use std::fmt;

#[derive(Debug)]
enum Suit {
    Heart,
    Diamond,
    Spade,
    Club
}

impl fmt::Display for Suit {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
       write!(f, "{:?}", self)
    }
}

fn main() {
    let heart = Suit::Heart;
    println!("{}", heart);
}

我不明白...如果使用derive(Debug),为什么要使用fmt::Display呢?这与以下代码片段是相同的:#[derive(Debug)] enum Suit { Heart } fn main() { let heart = Suit::Heart; println!("{:?}", heart); }这就破坏了尝试创建一个Display的整个目的。 - fsan
1
我建议实现std::fmt::Display,因为在大多数情况下这是最常见的期望。 - raugfer

3

你需要使用 "{:#?}" 进行格式化。 现在就可以工作了。

#[derive(Debug)]
enum Suit {
    Heart,
    Diamond,
    Spade,
    Club
}

fn main() {
    let s: Suit = Suit::Heart;
    println!("{:#?}", s); 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接