M.Hiroi's Home Page

お気楽 F# プログラミング超入門

書式付き出力関数


Copyright (C) 2022 Makoto Hiroi
All rights reserved.

F# の関数 printf はC言語の標準ライブラリ関数 printf に相当する関数です。いわゆる書式文字列を与えて、それに従ってデータを整形して出力します。これを「書式付き出力関数」といいます。ストリームのメソッド Write のように単純にデータを出力するのではなく、表示に関していろいろな指定を行うことができますが、その分使い方が少しだけ複雑になります。今回は書式付き出力関数について簡単に説明します。

●書式指定子

書式付き出力関数は F# のモジュール Printf に用意されています。Printf はデフォルトで open されているので、関数を呼び出すとき Printf を付ける必要はありません。基本的は関数を以下に示します。

printf  format args ... => stdout に出力
printfn format args ... => stdout に出力 (改行する)
eprintf  format args ...=> stderr に出力
eprintfn format args ...=> stderr に出力 (改行する)
fprintf  stream format args ... => stream に出力
fprintfn stream format args ... => stream に出力 (改行する)
sprintf  format args ... => string

printf は標準出力に、eprintf は標準エラー出力に、fprintf は stream に整形した結果を出力します。sprintf は整形した結果を文字列にして返します。名前の末尾に n が付く関数は最後に改行を出力します。

引数の文字列 format を書式文字列といい、出力に関する様々な指定を行います。書式文字列はそのまま文字列として扱われますが、文字列の途中にパーセント % が表れると、その後ろの文字を変換指示子として解釈し、引数に与えられたデータをその指示に従って表示します。

F# では % + 変換指示子 を「書式指定子」といいます。主な書式指定子を以下に示します。

%b   真偽値 (true, false)
%s   文字列
%c   文字 (Unicode)
%B, %d, %o, %x
     整数 (2, 10, 8, 16 進数)
%e, %f, %g
     浮動小数点数、複素数
%A   任意の値
%%   記号 % を表す

それから、% と変換指示子の間にオプションでいろいろな設定を行うことができます。

  1. フラグ
  2. フィールド幅
  3. 精度

これらのオプションは型指定子によって動作が異なる場合があります。

●整数の表示

簡単な例を示しましょう。

> printfn "%d, %x, %o" 100 100 100;;
100, 64, 144
val it: unit = ()

> printfn "[%d]" 10;;
[10]
val it: unit = ()

> printfn "[%4d]" 10;;
[  10]
val it: unit = ()

> printfn "[%4d]" 100000;;
[100000]
val it: unit = ()

> printfn "[%4d]" 123456;;
[123456]
val it: unit = ()

> printfn "[%-8d]" 123456;;
[123456  ]
val it: unit = ()

> printfn "[%08d]" 123456;;
[00123456]
val it: unit = ()

% の次の文字 d, x, o が変換指示子です。これらの指示子は整数を表示する働きをします。例が示すように、d は 10 進数、x は 16 進数、o は 8 進数で表示します。書式指定子の個数と与えるデータの数が合わないとエラーになるので注意してください。記号 % を出力したい場合は %% と続けて書きます。

整数値を表示する書式指定子は、データを表示するフィールド幅を指定することができます。最初の例がフィールド幅を指定しない場合で、次の例がフィールド幅を 4 に指定した場合です。10 ではフィールド幅に満たないので、右詰めに出力されています。もし、フィールド幅に収まらない場合は、指定を無視して数値を出力します。フィールド幅を 0 で埋めたい場合は、フラグに 0 を指定します。左詰めにしたい場合は、フラグに - を指定します。

●文字列の表示

%s は文字列を表示します。%s の場合でも、フィールド幅を指定することができます。簡単な例を示しましょう。

> printfn "%s" "hello, world";;
hello, world
val it: unit = ()

> printfn "[%s]" "hello, world";;
[hello, world]
val it: unit = ()

> printfn "[%20s]" "hello, world";;
[        hello, world]
val it: unit = ()

> printfn "[%-20s]" "hello, world";;
[hello, world        ]
val it: unit = ()

●文字の表示

%c は文字を表示します。%s と同様に、フィールド幅を指定することができます。簡単な例を示しましょう。

> printfn "%c" 'a';;
a
val it: unit = ()

> printfn "[%c]" 'a';;
[a]
val it: unit = ()

> printfn "[%4c]" 'a';;
[   a]
val it: unit = ()

> printfn "[%-4c]" 'a';;
[a   ]
val it: unit = ()

F# (.NET) の場合、文字はユニコード (unicode) で表されます。日本語 (漢字やカナなど) を文字として扱うこともできます。もちろん、%c で表示することができます。

> printfn "%c" 'あ';;
あ
val it: unit = ()

> printfn "[%c]" 'あ';;
[あ]
val it: unit = ()

> printfn "[%4c]" 'あ';;
[   あ]
val it: unit = ()

> printfn "[%-4c]" 'あ';;
[あ   ]
val it: unit = ()

F# の文字列は、配列のように角カッコを使って文字 (要素) を取り出すことができます。文字列の長さはプロパティ Length で求めることができますが、バイト数ではなく文字数になることに注意してください。

> let s1 = "abcde";;
val s1: string = "abcde"

> s1.Length;;
val it: int = 5

> let s2 = "あいうえお";;
val s2: string = "あいうえお"

> s2.Length;;
val it: int = 5

> for i = 0 to 4 do printfn "%c" s1.[i];;
a
b
c
d
e
val it: unit = ()

> for i = 0 to 4 do printfn "%c" s2.[i];;
あ
い
う
え
お
val it: unit = ()

●浮動小数点数の表示

浮動小数点数や複素数を表示するには %e, %f, %g を使います。

小数点の右側に印字される桁数は、%e と %f ではデフォルトで 6 桁になります。%g は整数部を含めて 6 桁で表示されます。これを変更するには精度を使います。精度はピリオド ( . ) のあとに数字を指定します。たとえば、"%.14f" とすると、小数点は 14 桁で表示されます。%g の場合、整数部を含めた桁数になります。小数点数の桁ではないので注意してください。

簡単な例を示します。

> let pi = System.Math.PI;;
val pi: float = 3.141592654

> printfn "%e" pi;;
3.141593e+000
val it: unit = ()

> printfn "%.14e" pi;;
3.14159265358979e+000
val it: unit = ()

> printfn "%f" pi;;
3.141593
val it: unit = ()

> printfn "%.14f" pi;;
3.14159265358979
val it: unit = ()

> printfn "%g" pi;;
3.14159
val it: unit = ()

> printfn "%.6g" pi;;
3.14159
val it: unit = ()

> printfn "%.14g" pi;;
3.1415926535898
val it: unit = ()

●%A 指定子

%A は任意のデータを表示します。整数は 10 進数で表示されますが、型を表す接尾辞が付加されることがあります。

> printfn "%d" 123;;
123
val it: unit = ()

> printfn "%A" 123;;
123
val it: unit = ()

> printfn "%d" 123L;;
123
val it: unit = ()

> printfn "%A" 123L;;
123L

浮動小数点数は %.10g で表示されます。

> printfn "%g" pi;;
3.14159
val it: unit = ()

> printfn "%A" pi;;
3.141592654
val it: unit = ()

> printfn "%.10g" pi;;
3.141592654
val it: unit = ()

文字列の場合、%A は " で囲って表示されます。文字の場合は ' で囲って表示されます。

> printfn "%s" "hello, world";;
hello, world
val it: unit = ()

> printfn "%A" "hello, world";;
"hello, world"
val it: unit = ()

> printfn "%c" 'A';;
A
val it: unit = ()

> printfn "%A" 'A';;
'A'
val it: unit = ()

他のデータ型の場合、基本的にはメソッド ToString を呼び出してデータを文字列に変換して出力します。

> type Foo(a: int) =
-   let x = a;;
type Foo =
  new: a: int -> Foo

> type Bar(a: int) =
-   let x = a
-   override this.ToString() = sprintf "Bar(%d)" x;;
type Bar =
  new: a: int -> Bar
  override ToString: unit -> string

> Foo(10) |> printfn "%A";;
FSI_0053+Foo
val it: unit = ()

> Bar(10) |> printfn "%A";;
Bar(10)
val it: unit = ()

このほかにも、書式付き出力関数にはいろいろな機能があります。詳細は F# のマニュアル「プレーンテキスト形式の書式設定」をお読みくださいませ。


初版 2022 年 5 月 28 日