今回はKotlinのformatメソッドに焦点を当て、その呼び出しと使い方についてお話したいと思います。
formatメソッドの呼び出し
まずは基本的な記述を見てみましょう。呼び出し方法は2種類あります。
println(String.format("%sと%s","谷口さん","橋本さん")) //谷口さんと橋本さん
println("%sと%s".format("谷口さん","橋本さん")) //谷口さんと橋本さん
この2つはどちらも同じ処理であり、結果は同じです。Java経験者の方には上の例の方が馴染み深い形かと思いますが、この記事のサンプルコードでは下側の呼び出し方を使用しています。
String.format("書式文字列",値1[,値2...])
"書式文字列".format(値1[,値2...])
String.format()
とした場合は第一引数に書式を指定した文字列(書式文字列。最終的な出力にプレースホルダを含んだもの)が入り、文字列メソッドとして呼び出した場合は呼び出し元が書式文字列になります。
書式文字列以外の引数は可変長引数なので、複数の値を渡すことができます。ただし、その可変長引数の数を超えて書式文字列側に「%」を記述してしまうと例外エラーになるので注意しましょう。
println("%sと%sと%s".format("谷口さん","橋本さん"))
//java.util.MissingFormatArgumentException: Format specifier '%s'
型指定子
上記の例で「%s」となっているのが書式指定部分です。書式文字列の中ではこの「%」の後に指定子というものを付け加えることで、引数の値をどのように表示するかを指定しています。
上の例では最もシンプルな「%型指定子」という形をとっています。
型指定子の種類
型指定子はその名の通り型を指定していますが、引数をどのような型として扱うかを指定するものです。型指定子には次のような種類があります。
指定子 | 意味 |
---|---|
s | String型 |
d | Int型 |
f | Double型 |
F | Float型 |
t | 日付時刻 (tの後に何を表示するか指定する必要がある) |
b | Boolean型 |
o | 整数(8進数) |
x | 整数(16進数) |
e | 指数表記 |
% | %を文字として表示 |
n | プラットフォーム固有の改行文字 |
ここで注意しておきたいのは引数の型が何であれ、「それを何として扱うか」ということです。例えば
println("%x".format(123)) //7b
Int型の123を16進数として扱いたければxを使用し、
println("%e".format(1000000.0)) //1.000000e+06
Double型を指数表記したければeを使用します。
ただしInt型をDouble型として扱うといったことは、そのままではできず例外となります。例外を回避するには引数の123をtoDouble()であらかじめDouble型に変換しておきましょう。
println("%f".format(123))
//IllegalFormatConversionException: f != java.lang.Integer
その他の指定子
ここからは型以外を指定する指定子をご紹介します。
精度指定子
精度指定子は少数に使った場合、小数点以下の桁数を指定します。指定したい桁数の前にドット(.)を付けて、型指定子の左側で使います。
println("%.3f".format(3.1415926535)) //3.142
上の例では引数をDouble型として扱い、小数点第3位まで表示し、それ以下の桁は四捨五入になります。
また文字列に使用した場合は、その文字列を指定した文字数で切り取り、後の文字は切り捨てます。
println("%.2s".format("転生したらスライムだった件")) //転生
表示幅指定子
表示幅指定子は結果が何文字であるかに関わらず、指定した桁数で出力されます。精度指定子の左側で記述します。
println("%9.3f".format(3.1415926535)) // 3.142
実行結果にスペースが追加されているのが分かると思います。デフォルトでは出力結果が指定した文字数に満たない場合、左側にスペースが挿入されます。
println("%12s".format("キングダム")) // キングダム
精度指定子を省略しても同じ結果です。
アラインメント指定子 (左寄せ)
表示幅指定子のデフォルトは上記の通り右寄せになりますが、これを「左寄せ」にしたい場合、表示指定子の直前にハイフン(-)を追加します。
println("%-9.3f".format(3.1415926535)) //3.142 |ここまでスペース
println("%-10s".format("化物語")) //化物語 |ここまでスペース
区切り指定子 (数値の3桁区切り)
数値に3桁区切りでカンマを付けるのであればカンマを指定します。場所はこの後に出てくるパディング指定子より右側、他の指定子より左側。ハイフンやアンダースコアは不可です。
println("%,d".format(1234567)) //1,234,567
println("%0,12d".format(1234567)) //0001,234,567
またこの状態でゼロ埋めする場合は、カンマも1桁として数えられるという点に注意しましょう。
パディング指定子 (ゼロ埋め)
表示幅指定子の桁埋めのための文字はデフォルトではスペースです。これを変更するにはパディング指定子で指定します。
表示幅指定子の左側に「0」を追加することで、いわゆるゼロ埋めが実現できます。
println("%09.3f".format(3.1415926535)) //00003.142
ただしString型に対しては使用できません。機能的にはreplaceメソッドで代用できるので、そちらを試してみるのもいいでしょう。
println("%10s".format("化物語").replace(" ","*")) //*******化物語
符号指定子
符号を付ける指定子です。デフォルトの状態では負数にマイナス(-)は付きますが正数にプラス(+)が付きません。
プラス記号を付け加えたいのであれば%の右側に+を記述します。
println("%+09.3f".format(3.1415926535)) //+00003.142
引数のインデックス番号指定
最後に関数が引数を複数取った場合、その引数を指定する方法をご紹介します。
println("%s%s%s".format("佐","藤","健")) //佐藤健
println("%s%s".format("佐","藤","健")) //佐藤
println("%s%s%s%s".format("佐","藤","健")) //Error
引数を複数取った場合、基本的に書式文字列を表す%の数は引数より少ないか、同じでなければなりません。
これは[%指定子]1つ1つが引数1つに対応しているためです。
そのため与える引数の順番が変わってしまうと、最終的に出力される文字列そのものも変わってしまいます。
println("%s%s%s".format("健","藤","佐")) //健藤佐
あるいは「同じものを複数回出力したい」場合、その回数と同じだけ引数を渡さなければならないということにもなります。これは非常に面倒で格好悪いです。
println("%s目%s耳%s耳%s目".format("右","右","右","右")) //右目右耳右耳右目
この問題を解消するために書式文字列では、引数のインデックス番号を指定することができるようになっています。
println("%3\$s%2\$s%1\$s".format("健","藤","佐")) //佐藤健
println("%1\$s目%1\$s耳%1\$s耳%1\$s目".format("右")) //右目右耳右耳右目
その場所で「引数の何番目を扱うか」を指定するには、上記の例のように「インデックス番号\$」で指定しましょう。
「$」はテンプレート文字列で使用する記号のため、エスケープ文字としてバックスラッシュが必要であることと、インデックス番号が1始まりという点に注意です。