フォーマット出力
この章では、std.format
モジュールの機能について説明する。D言語のコア機能については説明しない。
std
というプレフィックスを持つすべてのモジュールと同様に、std.format
はDの標準ライブラリであるPhobos内のモジュールだ。この本ではPhobosを完全に解説するだけのスペースがない。
Dの入力および出力フォーマット指定子は、C言語のものと似ている。
さらに進む前に、ご参考までにフォーマット指定子とフラグを要約しておく。
- | 左揃え |
+ | 符号を表示する |
# | 別の方法で表示する |
0 | ゼロ埋め表示 |
スペース | スペース埋め表示 |
s | 8進数 | |
b | バイナリ | |
d | 10進数 | |
o | 8進数 | |
x | X | 16進数 |
f | F | 標準的な十進表記法における浮動小数点数 |
e | E | 科学記法における浮動小数点数 |
a | A | 16進数記法における浮動小数点数 |
g | G | eまたはf |
, | 数字の区切り文字 | |
( | 要素フォーマット開始 | |
) | 要素フォーマット終了 | |
| | 要素区切り文字 |
これまで、必要な出力結果を表示するために、writeln
のような複数のパラメータを持つ関数を使用してきた。パラメータは文字列に変換されてから
出力に送られる。
場合によっては、これだけでは不十分だ。出力は、非常に特定の形式である必要がある場合がある。請求書の項目を出力するために使用される次のコードを見てみよう:
出力:
アイテム1 | 1.23 |
---|---|
アイテム2 | 45.6 |
情報は正しいものの、別の形式で出力する必要がある場合がある。例えば、小数点(この場合はドット)を揃える必要があり、小数点の後には常に2桁の数字が来るようにする必要がある場合などである。
アイテム1 | 1.23 |
---|---|
アイテム2 | 45.60 |
このような場合、フォーマットされた出力は便利だ。これまで使用してきた出力関数には、名前にf
という文字を含む対応する関数がある。writef()
およびwritefln()
である。f
は、formatted(フォーマット)の略だ。これらの関数の最初のパラメータは、他のパラメータの出力方法を記述するフォーマット文字列である。
例えば、writefln()
は、次のフォーマット文字列を使用して、上記の出力を作成することができる。
フォーマット文字列には、出力にそのまま渡される通常の文字と、表示される各パラメーターに対応する特殊なフォーマット指定子が含まれる。フォーマット指定子は、%
文字で始まり、フォーマット文字で終わる。上記のフォーマット文字列には、%d
と%9.02f
の2つのフォーマット指定子がある。
各指定子は、通常、出現順に、それぞれのパラメータに関連付けられる。例えば、%d
はi + 1
に関連付けられ、%9.02f
はitems[i]
に関連付けられる。各指定子は、それに対応するパラメータのフォーマットを指定する。(フォーマット指定子にはパラメータ番号も付けることができる。これについては、この章の後半で説明する。)
フォーマット文字列のうち、フォーマット指定子の一部ではないすべての文字は、そのまま表示される。上記のフォーマット指定子内の通常の文字は、 "Item %d:%9.02f"
で強調表示されている。
フォーマット指定子はいくつかの部分で構成されており、そのほとんどはオプションである。位置という部分は、後で説明する。その他は次の通りだ。(注釈:これらの部分の間のスペースは、読みやすくするために挿入したもので、指定子の一部ではない。)
% | フラグ | 幅 | セパレーター | 精度 | フォーマット文字 |
先頭の%
文字と末尾のformat文字は必須で、他の部分はオプションだ。
%
はフォーマット文字列では特別な意味を持つため、%
を通常の文字として出力するには、%%
と入力する必要がある。
フォーマット文字
x
およびX
: 整数引数は16進数で表示される。x
を使用する場合は小文字で、X
を使用する場合は大文字で表示される。
d
: 整数引数は10進数で出力される。符号付き型で値が0未満の場合は、負の符号も出力される。
バイナリ | 1100 |
---|---|
8進数 | 14 |
16進数 | c |
10進数 | 12 |
- 小数点の前には1桁の数字
- 精度が0以外の場合、小数点
- 小数点以下の必要な桁数(精度によって決定され、デフォルトの精度は6桁)
e
文字(10の累乗を意味する)- 指数が0未満の場合は"
-
"、0以上の場合は"+
"の文字 - 指数(少なくとも2桁からなる)
f
およびF
: 浮動小数点引数は10進数で出力される。小数点の前には少なくとも1桁の数字があり、小数点以下の桁数はデフォルトで6桁になる。
g
f
と同じ。ただし、指数が-5からprecisionの間である場合。それ以外はe
と同じ。precisionは、小数点以下の桁数を指定するのではなく、値全体の有効桁数を指定する。小数点以下の有効桁がない場合、小数点は出力されない。小数点以下の右端の0は出力されない。
- 文字
0x
- 単一の16進数桁
- 小数点(精度が0以外の場合)
- 小数点記号以降の必要な桁数(精度によって決定される);精度が指定されていない場合は、必要なだけの桁数
p
文字(2の累乗を意味する)- 指数が0より小さい場合は
-
、大きい場合は+
の文字 - 少なくとも1桁の指数 (値0の指数は0)
eとともに | 1.234568e+02 |
---|---|
fとともに | 123.456789 |
gとともに | 123.457 |
aとともに | 0x1.edd3c07ee0b0bp+6 |
s
: 値は、引数の型に応じて、通常の出力と同じように表示される。
bool
true
またはfalse
- 整数値と同じ
%d
- 浮動小数点値は
%g
- UTF-8エンコーディングの文字列。precisionは使用するバイトの最大数を決定する(UTF-8エンコーディングでは、バイト数は文字数と同じではないことに注意。例えば、文字列"ağ"は2文字で構成され、合計3バイトになる)。
- その型の
toString()
メンバー関数の戻り値としての構造体およびクラスオブジェクト。精度によって、使用するバイトの最大数が決まる。 - 配列を、その要素値として並べて
bool | true |
int | 365 |
double | 9.87 |
string | formatted |
object | File(55738FA0) |
array | [2, 4, 6, 8] |
width
この部分は、引数が表示されるフィールドの幅を決定する。幅が文字*
として指定されている場合、実際の幅の値は次の引数から読み込まれる (その引数はint
でなければならない)。幅が負の値の場合、-
フラグが指定されているとみなされる。
10文字のフィールド | 100 |
---|---|
5文字のフィールド | 100 |
separator
カンマ文字は、数値の桁をグループで区切るために使用される。グループのデフォルトの桁数は3だが、カンマの後に指定することができる:
1,234.567,800
1,000,000
1,00,00,00
桁数を*
で指定した場合、実際の桁数は次の引数から読み込まれる(その引数はint
でなければならない)。
1,0,0,0,0,0,0
同様に、コンマの後ろに疑問符を付け、数字の前に追加の引数として文字を指定することで、区切り文字を指定することもできる:
1.000.000
precision
精度は、フォーマット指定子のドットの後に指定する。浮動小数点型の場合、値の出力表現の精度を決定する。精度が文字*
として指定された場合、実際の精度は次の引数から読み込まれる (その引数はint
でなければならない)。負の精度値は無視される。
1234.5679
1.23e+03
1234.56789000
1234.568
番号 | 0.1235 |
---|
フラグ
複数のフラグを指定できる。
-
: 値はそのフィールドの左端に揃えて表示される。このフラグは、0
フラグを無効にする。
通常右揃え | | 123| |
---|---|
左揃え | |123 | |
+
: 値が正の場合、その前に+
文字が付けられる。このフラグはスペースフラグをキャンセルする。
負の値には効果がない | -50 |
---|---|
+フラグが付いた正の値 | +50 |
+フラグなしの正の値 | 50 |
#
:format_characterに応じて、値を別の形式で出力する。
o
: 8進値の最初の文字は常に0として表示されるx
とX
: 値が0以外の場合、その前に0x
または0X
- 浮動小数点数: 小数点以下の有効桁数が0でも小数点が表示される
g
およびG
: 小数点以下の桁数が0でも、小数点以下の桁数が0でも表示する
8進数は0から始まる | 01750 |
---|---|
16進数は0xで始まる | 0x3e8 |
小数点記号が不要な場合でも含まれる | 1.00000 |
右端のゼロが表示される | 1.20000 |
0
: フィールドは0で埋められる(値がnan
またはinfinity
でない場合)。精度も指定されている場合、このフラグは無視される。
8文字のフィールド | 00000042 |
---|
スペース文字: 値が正の場合、負の値と正の値を揃えるために、先頭にスペース文字が挿入される
負の値には効果がない | -34 |
---|---|
正の値とスペース | 56 |
スペースなしの正の値 | 56 |
位置パラメーター
上記で、引数がフォーマット文字列の指定子と1つずつ関連付けられることを説明した。フォーマット指定子内で位置番号を使用することも可能だ。これにより、指定子を特定の引数に関連付けることができる。引数は1から順に番号が付けられる。引数の番号は、%
文字の直後に指定し、$
で区切る:
% | 位置$ | フラグ | 幅 | 精度 | フォーマット文字 |
位置パラメーターの利点は、同じフォーマット文字列内で同じ引数を複数の場所で使用できることだ:
上記のフォーマット文字列では、4つの指定子内で番号1の引数を使用して、10進数、16進数、8進数、2進数の形式で出力している:
10進数 | 16進数 | 8進数 | 2進数 |
---|---|---|---|
42 | 2a | 52 | 101010 |
位置パラメータのもう1つの用途は、複数の自然言語のサポートだ。位置番号で参照される引数は、特定の言語の特定のフォーマット文字列内の任意の場所に移動できる。例えば、特定の教室の生徒数を次のように出力できる。
1A教室には20人の生徒がいる。
プログラムがトルコ語もサポートする必要があると仮定しよう。この場合、フォーマット文字列はアクティブな言語に応じて選択する必要がある。次のメソッドは三項演算子を活用している:
残念ながら、引数を1つずつ関連付けると、トルコ語のメッセージでは教室と生徒数の情報が逆順で表示される。教室の情報が生徒数の位置にあり、生徒数が教室の位置にある:
20 sınıfında 1A öğrenci var. ← 間違い: "20組"と"1Aの生徒"を意味する!
これを回避するには、引数を番号で指定し、1$
や2$
のように、各指定子を正確な引数と関連付けることができる:
これで、選択した言語に関係なく、引数が正しい順序で表示されるようになった:
1A教室には20人の生徒がいる。
1A sınıfında 20 öğrenci var.
フォーマットされた要素の出力
フォーマット指定子は %(
と %)
の間のフォーマット指定子は、コンテナ(例: 配列や範囲)のすべての要素に適用される:
上記のフォーマット文字列は3つの部分から構成されている:
%(
: 要素のフォーマット開始%s
: 各要素のフォーマット%)
: 要素のフォーマット終了
各部分は、 %s
要素は順番に表示される:
1234
要素形式の前後の通常の文字は、各要素について繰り返される。例えば、 {%s},
指定子は、波括弧で囲まれた要素をカンマで区切って表示する:
ただし、フォーマット指定子の右側の通常の文字は要素区切り文字とみなされ、要素の間のみ表示され、最後の要素の後は表示されない:
{1},{2},{3},{4 ← '}'と','は最後の要素の後に表示されない
%|
は、最後の要素でも表示されるべき文字を指定するために使用される。 %|
の文字は区切り文字とみなされ、最後の要素では表示されない。逆に、 %|
の文字は最後の要素でも表示される。
例えば、次のフォーマット指定子では、最後の要素の後に閉じ中括弧は表示されるが、コンマは表示されない。
{1},{2},{3},{4} ← '}'は最後の要素の後に表示される
個々に表示される文字列とは異なり、要素として表示される文字列は二重引用符で囲まれて表示される:
"spinach" | "asparagus" | "artichoke" |
ダブルクォートを不要にする場合は、要素フォーマットを %-(
で開始する必要がある。 %(
で開始する必要がある:
spinach | asparagus | artichoke |
文字にも同じことが適用される。 %(
はそれらをシングルクォートで囲んで出力する:
'h' | 'e' | 'l' | 'l' | 'o' |
%-(
はそれらを引用符なしで出力する:
hello
連想配列には、2つのフォーマット指定子が必要である。1つはキー用、もう1つは値用だ。例えば、次の %s (%s)
指定子は、まずキーを、次に値を括弧で囲んで出力する。
また、指定されている場合、最後の要素のコンマは表示されないことに注意。 %|
指定されているため、最後の要素のコンマは表示されないことに注意しよう:
1 (one), | 100 (hundred), | 10 (ten) |
format
フォーマットされた出力は、std.string
モジュールにあるformat()
関数でも利用できる。format()
はwritef()
と同じように動作するが、結果を出力に表示するのではなく、string
として返す。
この結果は、後の式で使うことができる。
フォーマット文字列のチェック
標準ライブラリには、フォーマット文字列 (writef
、writefln
、formattedWrite
、readf
、formattedRead
など) を受け取る、format
のような関数の代替構文がある。これらの関数には、フォーマット文字列をテンプレート引数として指定して、フォーマット文字列と引数の有効性をコンパイル時にチェックすることができる。
上記の!
文字はテンプレートインスタンス化演算子で、後で説明する。
(注釈:この構文は、コンパイル時にプログラマーの潜在的なエラーを検出できるため、より安全だが、コンパイル時間が長くなる可能性がある。
演習
- 値を読み込んで16進数で出力するプログラムを書いてみよう。
- 浮動小数点値を読み込み、小数点以下2桁のパーセンテージ値として出力するプログラムを作成しよう。例えば、値が1.2345の場合、
%1.23
と出力される必要がある。