C言語ユーザーのJavaへの不満とは?
C言語ユーザーの方がJavaを用いるときに聞かれる不満として、最も多いことの1つが「printfに該当する機能がない(使いづらい)」ではないかと思います。
この「出力形式設定」機能については、JDK 1.4までは、java.textパッケージのFormatクラスとそのサブクラスを用いることが解決策でしたが、決して使いやすい仕様ではありません。よって、C言語で作成されたプログラムをJavaに移植する場合のネックの1つと呼ばれることもあります。
これに対してJava 5では、PrintStreamクラスにprintfメソッドが追加されました。このメソッドは「書式付き文字列を、指定された書式文字列と引数を使用し、この出力ストリームに書き込む便利な方法」です。
Java 5の書式付き出力は、C言語のprintfの影響を大きく受けています。よって、書式文字列はC言語のそれに似ていますが、Java言語に対応し、その機能を活用するために、一部がカスタマイズされています。ですから、この違いに注意が必要です。
JavaのprintfはC言語よりも厳密
また、Javaでの書式は、C言語よりも厳密になっています。例えば、C言語では、適用不可能なフラグを指定した場合、無視されるだけですが、Javaでは例外となる場合があります。
しかし、ポインタのようなC言語とJavaの言語仕様の違いにかかわることや、一部の書式を除き、C言語のprintf関数における書式設定をほぼそのまま利用できます。
一例として一般的な書式付き出力を用いたCプログラムを示します。
このCプログラムと同じ動作をするJavaプログラムは以下のようになります。
ご覧のとおり、このCプログラムで用いている一般的な書式指定は、まったくそのままJavaで使えることが分かります。
C言語のprintf関数とJavaのprintfメソッドの相違点13!
では、C言語のprintf関数でよく用いられる書式指定のうち、Javaでは使えなかったり動作・意味が異なるものをいくつか挙げます。
(1) フラグ「#」
C言語では「#」をフラグに指定すると代替形式となり、基数を表すプレフィックスの出力などが可能になりますが、Javaでは、変換に依存する代替フォームを使用する必要があります。よって、これを怠った場合、C言語では適用不可能なフラグとして無視されるだけですが、Java言語では変換がフラグと互換性がないとして例外がスローされますので、注意が必要です。
(2) 長さ修飾子
C言語では、実引数の型を示す長さ修飾子を指定することができますが、Javaではこの指定方法はありません。
(3) 変換指定子「d」
10進整数に書式設定することは変わりませんが、Javaでは地域対応アルゴリズムが適用されますので、実行時のロケールによって出力結果の変換が行われる場合があります。
また、Javaでは、「#」フラグが指定されている場合、例外がスローされます。
(4) 変換指定子「i」
C言語では、10進整数として書式設定する「d」と同様に指定できますが、Javaでは存在しません。指定すると例外がスローされます。
(5) 変換指定子「u」
C言語では、10進符号なし整数に設定しますが、Javaでは存在しません。指定すると例外がスローされます。
(6) 変換指定子「e」
浮動小数点表示形式に設定することは変わりませんが、Javaでは地域対応アルゴリズムが適用されますので、実行時のロケールによって出力結果の変換が行われる場合があります。
また、Javaでは日付の書式設定において「月の何日目かを表す日」にも用いられます(小文字の「e」のみ)。
(7) 変換指定子「E」
大文字の浮動小数点表示形式に設定することは変わりませんが、Javaでは地域対応アルゴリズムが適用されますので、実行時のロケールによって出力結果の変換が行われる場合があります。
(8) 変換指定子「f」
10進数浮動小数点数形式に設定することは変わりませんが、Javaでは地域対応アルゴリズムが適用されますので、実行時のロケールによって出力結果の変換が行われる場合があります。
(9) 変換指定子「g」
C言語では変換指定子「e」による形式か「f」による形式のうち適した方となっていますが、Javaでは一般の科学表記法を使用して出力を書式設定します。また、地域対応アルゴリズムが適用されますので、実行時のロケールによって出力結果の変換が行われる場合があります。
(10) 変換指定子「a」
16進数浮動小数点数形式に設定することは変わりませんが、Javaでは日付の書式設定においてロケール固有の曜日の短縮名(例:「Sun」「Mon」)の指定にも、用いられます。
(11) 変換指定子「A」
大文字の16進数浮動小数点数形式に設定することは変わりませんが、Javaでは日付の書式設定においてロケール固有の曜日の完全な名前(例:「Sunday」「Monday」)の指定にも、用いられます。
(12) 変換指定子「p」
C言語ではポインタの値に設定しますが、Javaでは該当する概念がなく、時刻の書式設定においてロケールに特定の午前または午後の小文字(am、または、pmなど)のマーカの指定に用います。まったく概念が異なりますので注意が必要です。
(13) 変換指定子「n」
C言語では、整数変数に出力済み文字数を格納することを設定しますが、Javaでは、プラットフォーム固有の行区切り文字を設定します。まったく概念が異なりますので、注意が必要です。
Javaのprintfメソッドで拡張された書式指定
Javaのprintfメソッドには、C言語のprintf関数にはなかった書式や指定方法が数多く追加されています。詳細はAPIドキュメントなどをご覧ください。
なお、それらの新しい活用術のいくつかについては、今後の「Java TIPS」にて順次紹介していきます。
Copyright © ITmedia, Inc. All Rights Reserved.