LoginSignup
12

More than 5 years have passed since last update.

[D言語] writef の書式指定子について

Last updated at Posted at 2015-07-29

D言語のwritefprintfとは少し違う

D言語のwritefは、C言語のprintfと同じもので
書式指定子は全く同じと思っていたのですが、
違うところがあるようなので、簡単に調べてみました。

書式指定子についての説明は、writefが内部的に
呼び出しているformattedWriteドキュメント
に書いてあります。内容をざっくりと要約すると

  • 基本はprintfの書式指定子を踏襲
  • %sは文字列ではなく型のプレースホルダ
  • %(%)で囲むと、配列の要素を順に表示できる

%sは文字列ではなく型のプレースホルダ

迷ったら、とりあえず%sにしておけばOK!
型に合わせて、適切に処理してくれます。
ユーザー定義型の場合、toString()メソッドが呼ばれます。

D
struct Hoge { string toString() { return "hoge"; } }

void main()
{
    import std.stdio, std.math;

    int    n = 123;
    real   r = PI;
    string s = "hello";
    Hoge   h;
    writef("%s, %s(%.11s), %s, %s", n, r, r, s, h);
}
Output
123, 3.14159(3.1415926536), hello, hoge

%(%)で囲むと、配列の要素を順に表示できる

%(%)の間に配列を指定すると、全ての要素を順に表示してくれます。

D
void main()
{
    import std.stdio;

    int[] arr = [0, 1, 2, 3, 4];
    writef("%s",      arr);
    writef("%(%s %)", arr);
}
Output
[0, 1, 2, 3, 4]
0 1 2 3 4

要素%s%)との間の内容は、暗黙的に区切り文字として扱われます。
上の例では、半角スペースが区切り文字です。
区切り文字は、要素間にのみ挿入され、末尾要素の後ろには挿入されません。

D
    writef("%(%s, %)", arr);
Output
0, 1, 2, 3, 4

区切り文字は,(カンマと半角スペース)で、
「4」の後ろには挿入されていません。

文字や文字列の配列を表示する場合、'"が表示されますが、%-(でエスケープできます。

D
    char[]   cs = ['a', 'b', 'c', 'd'];
    string[] ss = ["hoge", "fuga", "piyo"];
    writefln("%s / %s",             cs, ss);
    writefln("%(%s,%) / %(%s,%)",   cs, ss);
    writefln("%-(%s,%) / %-(%s,%)", cs, ss);
Output
abcd / ["hoge", "fuga", "piyo"]
'a','b','c','d' / "hoge","fuga","piyo"
a,b,c,d / hoge,fuga,piyo

更に、多次元配列(ネストした配列)を表示することも可能です。

D
    int[][] mat = [[0, 1], [2, 3], [4, 5]];
    writef("%(%(%s %)\n%)", mat);    
}
Output
0 1
2 3
4 5

内側の配列(int[] )の区切り文字が半角スペースで、
外側の配列(int[][])の区切り文字が\n(改行)です。
非常に便利です!

ですが、区切り文字をカスタマイズしたい時があります。
例えば、括弧、スペース、改行で、いい感じにインデントを揃えたい時に

D
    writef("(%([%(%s %)]\n %))", mat);
Output
([0 1]
 [2 3]
 [4 5)

いい感じなのですが、末尾の]が抜けました。
これは、]が暗黙的な区切り文字に含まれていたために、
末尾要素の後ろに挿入されなかったためです。

こんな場合に、明示的に区切り文字を指定できる%|(※Lではなく縦線)があります。
%|【区切り文字】のように使用します。

D
    writef("(%([%(%s %)]%|\n %))", mat);
Output
([0 1]
 [2 3]
 [4 5])

上の例では、区切り文字を明示的に\n(改行と半角スペース)としたことで、
]を区切り文字から除外でき、意図した通り表示されました。

その他

その他にもbool型などは、%sだとtrue/falseで表示され、%bだと1/0で表示されるなど、
細かくは色々あると思うのですが、詳しくは元のドキュメントに当たってください。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12