🦀

[Rust] 構造体や列挙型の表示 < Debug / Display >

2022/08/27に公開

構造体や列挙型を表示したい

  • 構造体や列挙型などの変数をprintln!()で表示しようとするとエラーになる
  • それぞれ要素を取り出してやれば表示することは可能
表示エラー
struct Foo {
    value: u32,
    string: &'static str,
}

fn main() {
    
    let x = Foo {
        value: 123,
        string: "abc",
    };

    println!("{}", x);      // 表示が出来ずエラー
}

デバッグによる表示 Debug

  • 型の定義に#[derive(Debug)]のアトリビュートを付ければデバッグによる表示が可能
  • プレースホルダ{:?}もしくはマクロdbg!()で表示をする
デバッグによる表示
#[derive(Debug)]    // デバッグのアトリビュート
struct Foo {
    value: u32,
    string: &'static str,
}

fn main() {
    
    let x = Foo {
        value: 123,
        string: "abc",
    };

    println!("{:?}", x);    // デバッグ表示( dbg!(x) でも可)
}
実行結果(ターミナル)
Foo { value: 123, string: "abc" }

Displayトレイトの実装 std::fmt::Display

構造体の場合

  • 型の定義にstd::fmt::Displayのトレイトを実装すると、自由に表示を設定することが可能
  • write!()にどのように表示するかを設定する
Displayトレイトの実装(構造体)
use std::fmt;   // フォーマットの標準ライブラリクレート

struct Foo {
    value: u32,
    string: &'static str,
}

impl fmt::Display for Foo {     // Display のトレイトの実装

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "value = {}\nstring = {}", self.value, self.string)
    }
}

fn main() {

    let x = Foo {
        value: 123,
        string: "abc",
    };

    println!("{}", x);
}
実行結果(ターミナル)
value = 123
string = abc

列挙型の場合

  • 列挙型はmatchでそれぞれのパターンを設定する必要がある
Displayトレイトの実装(列挙型)
use std::fmt;   // フォーマットの標準ライブラリクレート

enum Foo {
    X,
    Y(u32),
    Z { value: u32, string: &'static str },
}

impl fmt::Display for Foo {     // Display のトレイトの実装

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Self::X                         => write!(f, "X"),
            Self::Y(n)                      => write!(f, "{}", n),
            Self::Z { value: n, string: m } => write!(f, "x = {} / y = {}", n, m),
        }
    }
}

fn main() {

    let x = Foo::X;
    let y = Foo::Y(123);
    let z = Foo::Z {
        value: 456,
        string: "abc",
    };

    println!("{}", x);
    println!("{}", y);
    println!("{}", z);
}
実行結果(ターミナル)
X
123
x = 456 / y = abc

write!()の応用

  • write!()には変数の要素と関係ない文字列や記号、絵文字などを設定することも可能
絵文字を表示
use std::fmt;   // フォーマットの標準ライブラリクレート

enum Foo {
    X,
    Y,
    Z,
}

impl fmt::Display for Foo {

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Self::X => write!(f, "Hello!"),         // 文字列
            Self::Y => write!(f, "('ω')ノ"),        // 記号
            Self::Z => write!(f, "\u{1f600}"),      // 絵文字
        }
    }
}

fn main() {

    let x = Foo::X;
    let y = Foo::Y;
    let z = Foo::Z;

    println!("{}", x);
    println!("{}", y);
    println!("{}", z);
}
実行結果(ターミナル)
Hello!
('ω')ノ
😀

Discussion