連載
» 2007年05月29日 10時00分 UPDATE

JavaTips 〜Javaプログラミング編:[Java 5]C言語からの移植に便利なprintfの注意点

[平野正喜,@IT]

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プログラムを示します。

図1 一般的な書式付き出力を用いたCプログラム 図1 一般的な書式付き出力を用いたCプログラム

 このCプログラムと同じ動作をするJavaプログラムは以下のようになります。

図2 上記のCプログラムと同じ動作をするJavaプログラム 図2 上記の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」にて順次紹介していきます。

Profile

RunDog.org

平野正喜


Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。