Chapter 13

フォーマット

フォーマット文字列

println! マクロの括弧内で,最初に書く文字列リテラルをフォーマット文字列といいます.フォーマット文字列の中のプレースホルダーは,続く引数の値で置き換えられます.

fn main() {
    let a = 120;
    let b = 450;
    println!("{} + {} = {}", a, b, a + b);
}
標準出力
120 + 450 = 570

今までは {} の中身が常に空でした.この章では, {} の中身でより詳細なフォーマットを指定する方法を紹介します.

ここで紹介する書き方は, print! マクロや assert! マクロなど他のいくつかのマクロでも使用できます.

順番

フォーマット文字列中に複数のプレースホルダーが存在したとき,今までは最初の引数が最初のプレースホルダー, 2 番目の引数が 2 番目のプレースホルダー……という順に置き換えられていました.

fn main() {
    println!("{} {} {} {} {}", -2, 10, 2.4, 30, 4.5);
}
標準出力
-2 10 2.4 30 4.5

{} の中に数字を書いて,この順番を変更することができます.

fn main() {
    println!("{2} {3} {0} {4} {1}", -2, 10, 2.4, 30, 4.5);
}
標準出力
2.4 30 -2 4.5 10

これを使うと同じ値を複数回出力することもできます.

fn main() {
    println!("{0} {0} {1} {1}", -2, 10);
}
標準出力
-2 -2 10 10

また,これを数字で指定する代わりに,一時的に名前を付けて使うこともできます.

fn main() {
    println!("{hoge} {fuga} {hoge}", hoge = -2, fuga = 10);
}
標準出力
-2 10 -2

単に -2 と書く代わりに hoge = -2 と書くと,フォーマット文字列中の {hoge}-2 で置き換えられます.

フォーマット形式

プレースホルダーで,コロン : に続く部分はフォーマットの形式を表します.

fn main() {
    println!("{:6}", 79);
}

: の後の 6 は, 6 桁で出力するということを意味します. 2 桁の整数 79 は,

標準出力
79

と出力される代わりに,前に 4 文字の空白を付け加えて

標準出力
    79

と出力されます.

{0} のような順番の指定と併用するときは, {0:6} のように書きます.

桁数の指定だけでなく,以下のように様々な指定が可能です.

フォーマット形式 出力 説明
{:6} 79     79 6桁(右寄せ)
{:06} 79 000079 6桁(0埋め)
{:<6} 79 79     6桁(左寄せ)
{:^6} 79   79   6桁(中央寄せ)
{:+} 79 +79 符号を明示
{:b} 79 1001111 2進法
{:o} 79 117 8進法
{:x} 79 4f 16進法(小文字)
{:X} 79 4F 16進法(大文字)
{:.4} 2.71828 2.7183 小数点以下 4 桁まで
{:e} 299792458 2.99792458e8 指数表記(小文字のe
{:E} 299792458 2.99792458E8 指数表記(小文字のE

書き方の一覧はここにあります.

デバッグ出力

タプルや配列は,そのまま出力することができません.

fn main() {
    let tuple = (10i32, 20i32, 30i32);
    println!("{}", tuple);
}

次のようなエラーになります.

error[E0277]: `(i32, i32, i32)` doesn't implement `std::fmt::Display`
 --> src/main.rs:3:20
  |
3 |     println!("{}", tuple);
  |                    ^^^^^ `(i32, i32, i32)` cannot be formatted with the default formatter
  |

タプルや配列を出力したいときは,

fn main() {
    let tuple = (10i32, 20i32, 30i32);
    println!("({}, {}, {})", tuple.0, tuple.1, tuple.2);
}

のように書く必要があります.

一方, : の後にクェスチョンマーク ? を付けて {:?} とすると,タプルや配列をそのまま出力することができます.

fn main() {
    let tuple = (10i32, 20i32, 30i32);
    println!("{:?}", tuple);
}
標準出力
(10, 20, 30)

これは,プログラムのどこかで異常が起きていると分かったとき,コード中に現れる変数の値をとにかく知りたいときに使われます.

{:?} を使うと,タプルや配列であってもその中身がもらさず全て出力されますが,形式などを細かく調整することはできず,次の 2 択になります.

  • {:?} …… 一行で出力される.
    (10, 20, 30)
    
  • {:#?} …… 改行をはさみながら出力される.
    (
        10,
        20,
        30,
    )