Provided by: manpages-ja-dev_0.5.0.0.20131015+dfsg-2_all
名前
printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - 指定された書 式に変換して出力を行う
書式
#include <stdio.h> int printf(const char *format, ...); int fprintf(FILE *stream, const char *format, ...); int sprintf(char *str, const char *format, ...); int snprintf(char *str, size_t size, const char *format, ...); #include <stdarg.h> int vprintf(const char *format, va_list ap); int vfprintf(FILE *stream, const char *format, va_list ap); int vsprintf(char *str, const char *format, va_list ap); int vsnprintf(char *str, size_t size, const char *format, va_list ap); glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照): snprintf(), vsnprintf(): _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L; or cc -std=c99
説明
printf() 関数グループは、以下で述べるように、 format に従って出力を生成するものである。 printf() と vprintf() は出力を stdout (標準出力ストリーム) に書き出す。 fprintf() と vfprintf() は出力を指定された出力 stream に書き出す。 sprintf(), snprintf(), vsprintf(), vsnprintf() は出力を文字列 str に書き込む。 snprintf() と vsnprintf() は最大で size バイトを str に書き込む (size には文字列を終端す る NULL バイト ('\0') もを含まれる)。 vprintf(), vfprintf(), vsprintf(), vsnprintf() の各関数はそれぞれ printf(), fprintf(), sprintf(), snprintf(), の各関数と等価であり、可変数引き数の代わりに va_list を引き数として 呼び出される点だけが異なる。 これらの関数では va_end マクロは呼び出されない。 これらの関数 は va_arg を呼び出すので、呼び出し後の ap の値は未定義である。 stdarg(3) を参照のこと。 これらの 8 つの関数は format 文字列の制御に従って出力を書き出す。 format 文字列は、これに 続く引き数 (または stdarg(3) の可変長引き数機構を使ってアクセスできる引き数) をどのよう に変換して出力するかを指定する。 C99 と POSIX.1-2001 では、 sprintf(), snprintf(), vsprintf(), vsnprintf() の呼び出し で、範囲が重複するオブジェクト間でコピーが発生する場合の 結果は不定であると規定されている (例えば、出力先の文字列と入力された 引き数の一つが同じバッファを参照している場合などであ る)。 「注意」の節を参照。 Return Values 成功時には、上記の関数は書き込まれた文字数を返す (文字列の最後を示すために使用する NULL バ イトは数に含まれない)。 snprintf() と vsnprintf() は、 size バイトを越える文字数を書き込まない (size には文字列 を終端する NULL バイト ('\0') も含まれる)。 この制限によって出力が切り詰められた場合には、 もし十分なスペースがあれば書き込まれたであろう文字の個数 (文字列を終端する NULL バイトを除 く) を返す。 従って、返り値が size 以上だった場合、出力が切り詰められたことを意味する (後 述の注意も参照のこと)。 エラーが発生した場合は、負の数を返す。 フォーマット文字列のフォーマット フォーマット文字列は文字の列で、 (もしあるなら) 初期シフト状態で始まり、初期シフト状態で終 わる。 フォーマット用の文字列は 0 個以上の命令 (directives) によって構成される。 命令に は、通常文字と変換指定 (conversion specifications) がある。 通常文字は % 以外の文字で、出 力ストリームにそのままコピーされる。 変換指定は、それぞれが 0 個以上の引き数を取る。 各変 換指定は文字 % で始まり、 変換指定子 (conversion specifier) で終わる。 % と変換指定子の間 には、0 個以上の フラグ 、 最小 フィールド幅 、 精度 、 長さ修飾子 を (この順序で) 置くこ とができる。 引き数は (型の格上げの後は) 変換指定子が表す型と正確に対応しなければならない。 デフォルト では、'*' や変換指定子が出てくる毎に次の引き数を要求され、 引き数は指定された順序で使用さ れていく (指定された引き数の個数が不十分ならエラーとなる)。 また、引き数が必要な箇所で '%' の代わりに "%m$"、 '*'の代わりに "*m$" と書くことで、 明示的にどの引き数を使用するかを指定 することもできる。 ここで 10進の整数 m は希望の引き数の引き数リストでの位置を示す (最初の 引き数の番号が 1 である)。 従って、 printf("%*d", width, num); と printf("%2$*1$d", width, num); は等価である。 二番目の書き方では同じ引き数を繰り返し参照することができる。 C99 標準には、 Single UNIX Specification 由来の '$' を使った書き方は含まれていない。 '$' を使ったスタイル を使うと、引き数を取る変換及び幅と精度の引き数を 全てこのスタイルで指定しなければならない が、 引き数を消費しない "%%" フォーマットと混ざっているかもしれない。 '$' で指定される引き 数の番号に空きがあってはならない。 例えば、もし引き数 1 と 3 が指定されると、引き数 2 も フォーマット文字列のどこかで 指定されなければならない。 数値変換には小数点や 1000 単位の区切り文字を使うものもある。 実際にどの文字を使うかはロ ケールの LC_NUMERIC による。 POSIX ロケールでは小数点に '.' を用い、 区切り文字は使わな い。 従って、 printf("%'.2f", 1234567.89); は、 POSIX ロケールでは "1234567.89" 、 nl_NL ロケールでは "1234567,89"、 da_DK ロケールで は "1.234.567,89" となる。 フラグ文字 % 文字の後ろには 0 個以上のフラグ文字が続く。 # 値は「別の形式」に変換される。 o 変換の場合、(先頭文字が 0 になっていない場合に先頭 に 0 を追加することで) 出力文字列の最初の文字を 0 にする。 x と X 変換の場合、数値 が 0 でないときには文字列 "0x" (X 変換の場合には "0X") が前に付与される。 a, A, e, E, f, F, g, G 変換では、 小数点に続く数字がなくても、 出力には常に小数点が含まれる (通常は、小数点の後に数字が続く場合にのみ、 小数点が表示される)。 g と G 変換の場 合、他の変換とは異なり、末尾のゼロが変換結果から削除されない。 その他の変換では、結 果は未定義である。 0 値をゼロで埋める。 d, i, o, u, x, X, a, A, e, E, f, F, g, G 変換では、変換した値の 左側を空白文字の代わりにゼロで埋める。 0 と - が両方とも指定された場合は、 0 フラグ は無視される。 精度が数値変換 (d, i, o, u, x, X) と同時に指定された場合には、 0 フ ラグは無視される。 その他の変換では、動作は未定義である。 - 変換値をフィールド境界で左揃えにする (デフォルトは右揃えである)。 n 変換以外で は、変換された値は 左側ではなく右側を空白文字やゼロで埋められる。 - と 0 の両方が指 定された場合には、 - が優先される。 ' ' (1個の半角スペース) 符号付き変換で生成された正の数字の前に空白 (または空文字列) が 置かれる。 + 符号付き変換によって出力される数字の前に、常に符号 (+ か -) が置かれる。 デフォルト では、符号は負の数字の場合のみ付与される。 + と半角スペースの 両方が使われている場 合には、 + が優先される。 上記の 5 つのフラグは C 標準で定義されている。 SUSv2 では、さらにもう一つフラグ文字が規定 されている。 ' 10進数変換 (i, d, u, f, F, g, G) において、ロケール情報に指定があれば 1000 単位の 区切り文字を出力する。 gcc(1) の多くのバージョンは、このオプションを解釈することが できず、 警告を出力することに注意せよ。 %'F は SUSv2 には含まれていない。 glibc 2.2 では、さらに一つフラグ文字が追加されている。 I 10進整数変換 (i, d, u) において、ロケールの代替出力数字があれば、それを用いて出力 する。 例えば、 glibc 2.2.3 以降では、ペルシア ("fa_IR") ロケールで アラビア数字 (Arabic-Indic digits) を出力できる。 フィールド幅 最小のフィールド幅を指定する 10進数の数値文字列 (文字列の最初の文字は ゼロ以外)。本項目は オプションである。 変換された値の文字数がフィールド長よりも少ない場合、 フィールドの左側を スペースで埋める (左揃えのフラグがある場合は右側を埋める)。 10進数の文字列の代わりに "*" や "*m$" (m は 10進整数) を書くこともできる。 "*" と "*m$" はそれぞれ、次の引き数と m 番目 の引き数をフィールド幅として 使うことを指定する (これらの引き数は int 型でなければならな い)。 フィールド幅に負の数が指定された場合は、 '-' フラグと正の数のフィールド幅として扱わ れる。 フィールド幅が小さかったり指定がなかったりしても、フィールドが切り詰められる ことは ない。もし変換結果がフィールド幅よりも広かった場合、 フィールドは変換結果が入る幅に広げら れる。 精度 オプションである精度は、ピリオド ('.') とそれに続く10進数という 形式で指定する (10進数はオ プション) 。 10進数の文字列の代わりに "*" や "*m$" (m は 10 進整数)を書くこともできる。 "*" と "*m$" はそれぞれ、次の引き数と m 番目の引き数を精度として 使うことを指定する (これ らの引き数は int 型でなければならない)。 精度として '.' だけが指定された場合、 精度はゼロ とみなされる。 精度が負の数だった場合、 精度は指定されなかったものとみなされる。 d, i, o, u, x, X 変換では、表示される最小の桁数を指定する。 a, A, e, E, f, F 変換では、小数点以下に 表示される数字の桁数を指定する。 g と G 変換では、有効数字の最大桁数を指定する。 s と S 変 換では、文字列から出力される最大文字数を指定する。 長さ修飾子 「整数変換」とは、 d, i, o, u, x, X 変換のことである。 hh 整数変換に対応する引き数が signed char か unsigned char で、 n 変換に対応する引き数 が signed char へのポインタであることを示す。 h 整数変換に対応する引き数が short int か unsigned short int で、 n 変換に対応する引 き数が short int へのポインタであることを示す。 l 各変換に対応する引き数が、 整数変換では long intか unsigned long int、 n 変換では long long int へのポインタ、 c 変換では wint_t、 s 変換では wchar_t へのポインタで あることを示す。 ll (エルエル) 整数変換に対応する引き数が long long int か unsigned long long int で、 n 変換に対 応する引き数が long int へのポインタであることを示す。 L a, A, e, E, f, F, g, G 変換に対応する引き数が long double であることを示す。 (C99 では %LF を使うことを認めているが、SUSv2 では認められていない。) q ("quad"。 4.4BSD と Linux libc5 のみ有効。使ってはならない。) ll と同じ意味であ る。 j 整数変換に対応する引き数が intmax_t か uintmax_t であることを示す。 z 整数変換に対応する引き数が size_t か ssize_t であることを示す。 (Linux libc5 で は、これを指定するのに Z を用いる。使ってはならない。) t 整数変換に対応する引き数が ptrdiff_t であることを示す。 SUSv2 で長さ修飾子として使用できるのは、 h (hd, hi, ho, hx, hX, hn), l (ld, li, lo, lx, lX, ln, lc, ls), L (Le, LE, Lf, Lg, LG) だけである。 変換指定子 適用される変換の型を指定する文字。 変換指定子とその意味は以下の通りである。 d, i int 引き数を符号付き 10 進表記に変換する。 精度指定があれば、精度で指定した桁数は必 ず出力される。変換後の値が 指定された桁数に足りない場合は、左側が 0 で埋められる。 デフォルトの精度は 1 である。 0 を表示しようとした時に、明示的に精度として 0 が指定 されていると、 出力は空文字列となる。 o, u, x, X unsigned int 引き数を、 符号なし8進数 (o), 符号なし10進数 (u), 符号なし16進数 (x と X) に変換する。 x 変換では abcdef が使用され、 X 変換では ABCDEF が使用される。 精 度指定があれば、精度で指定した桁数は必ず出力される。変換後の値が 指定された桁数に足 りない場合は、左側が 0 で埋められる。 e, E double 引き数を丸めて [-]d.ddde±dd の形に変換する。 小数点の前には一桁の数字があ り、小数点以下の桁数は精度で指定された桁数 になる。精度は指定されなかった場合 6 と みなされる。 精度が 0 の場合には、 小数点以下は表示されない。E 変換では、指数を表現 するときに (e で はなく) E が使われる。指数部分は少なくとも 2桁表示される。つまり、 指数の値が 0 の場合には、00 と表示される。 f, F double 引き数を丸めて [-]ddd.ddd の形の10進表現に変換する。 小数点の後の桁数は、精 度で指定された値となる。 精度が指定されていない場合には 6 として扱われる。 精度とし て明示的に 0 が指定されたときには、小数点以下は表示されない。 小数点を表示する際に は、小数点の前に少なくとも一桁は数字が表示される。 (SUSv2 では、F は規定されておらず、無限や NaN に関する文字列表現を 行ってもよいこと になっている。 C99 標準では、f 変換では、無限は "[-]inf" か "[-]infinity" と表示し、 NaN は文字列 の先頭に `nan' をつけて表示するように規定されている。 F 変換の場合は "[-]INF", "[-]INFINITY", "NAN*" と表示される。) g, G double 引き数を f か e (G 変換の場合は F か E) の形式に変換する。 精度は表示する桁 数を指定する。 精度が指定されない場合は、6桁とみなされる。 精度が 0 の場合は、1桁と みなされる。 変換される値の指数が、 -4 より小さいか、精度以上の場合に、 e 形式が使 用される。 変換された結果の小数部分の末尾の 0 は削除される。小数点が表示されるの は、 小数点以下に数字が少なくとも一つある場合にだけである。 a, A (C99 にはあるが SUSv2 にはない) a 変換では、 double 引き数を (abcdef の文字を使っ て) [-]0xh.hhhhp± 形式の 16 進表記に変換する。 A 変換では、前置文字列 0X, 文字 ABCDEF, 指数文字 P を用いる。 小数点の前には 1 桁の 16 進数が置かれ、小数点の後ろの 桁数は 精度で指定 された値となる。デフォルトの精度は、その値が 2 進数で正確に表現で きる 場合には、その値を正確に表現できる桁数となる。それ以外の場合は、 double 型の値 を区別するのに十分な大きさとなる。 小数点の前の数字は、 正規化されていない数の場合 はいくつになるか分からない。 正規化された数の 場合は、 0 以外の値になるが、いくつに なるかは分からない。 c l 修飾子がなければ、 int 引き数を unsigned char に変換して、その結果に対応する文字 を出力する。 l 修飾子があれば、 wint_t (ワイド文字) 引き数を、 wcrtomb(3) 関数を初 期シフト状態で呼び出してマルチバイト文字列に変換し、 変換されたマルチバイト文字列を 出力する。 s l 修飾子がない場合、 引き数は const char * 型で文字型の配列へのポインタ (文字列への ポインタ) であることが 期待されている。配列中の文字は、終端の NULL バイト ('\0') が出てくるまで出力される (終端文字は出力されない)。 精度が指定されていると、指定さ れた字数以上は出力されない。 精度が指定された場合には、終端バイトが存在する必要はな い。 精度が指定されていなかったり、精度の値が配列の大きさより大きい場合には、 配列 は終端の NULL バイトを含んでいなければならない。 l 修飾子が指定されている場合、 引き数は const wchar_t * 型でワイド文字の配列へのポ インタであることが期待されている。 配列中のワイド文字は (1文字毎に wcrtomb(3) を呼 び出して) マルチバイト文字に変換される (最初のワイド文字の変換の前に wcrtomb() の シフト状態を初期状態に戻してから変換は行われる)。 マルチバイト文字への変換は、文字 列を終端する NULL ワイド文字が 出てくるまで行われ、終端 NULL ワイド文字も含めて変換 される。 結果のマルチバイト文字列は、終端の NULL バイトが出てくるまで 出力される (終端の NULL バイトは出力されない)。 精度が指定された場合、指定されたバイト数以上に は出力されない。 但し、マルチバイト文字の一部分だけが出力されることはない。 精度は 「バイト」数を指定するものであり、「ワイド文字」数や 「画面での位置」を指定するもの ではないことに注意。 精度が指定されていて、さらに出力が配列の末尾に達する前に出力バ イト数が 精度の値を超える場合だけは、配列は NULL ワイド文字で終端されていなくてもよ い。 それ以外の場合は、必ず配列は NULL ワイド文字で終端されていなければならない。 C (C99 にはないが SUSv2 にはある) lc と同じ。使ってはならない。 S (C99 にはないが SUSv2 にはある) ls と同じ。使ってはならない。 p void * ポインタ引き数を (%#x や %#lx のような) 16 進数で出力する。 n これまでに出力された文字数を int * (または類似の型) のポインタ引き数が指す整数に保 存する。 引き数の変換は行われない。 m (glibc での拡張) strerror(errno) の出力を表示する。引き数は必要ない。 % '%' 文字を出力する。変換される引き数は無い。 変換指定全体を書くと "%%" となる。
準拠
fprintf(), printf(), sprintf(), vprintf(), vfprintf(), vsprintf() 関数は、C89 と C99 に準 拠している。 snprintf() と vsnprintf() は C99 に準拠している。 snprintf() の返り値を見ると、 SUSv2 と C99 標準は互いに矛盾している。 SUSv2 では、 snprintf() が size=0 で呼び出された場合、 1 未満の値を何か返り値とするように規定している。 一方 C99 では、このような場合 str を NULL とし、返り値として (通常通り) 出力バッファが十分 な大きさが あった場合に出力されるであろう文字数を返す。 Linux libc4 では、 5 つの C 標準のフラグ、 長さ修飾子 h, l, L、変換 c, d, e, E, f, F, g, G, i, n, o, p, s, u, x, X が使える。 但し F は f と同義である。 また、 D, O, and U を ld, lo, and lu と同じものとして使える (これはまずい仕様で、 後に %D の対応が打ち切られた時に深 刻なバグを 引き起こした)。ロケール依存の小数点、1000 区切り、 NaN と無限、 "%m$" と "*m$" は使えない。 Linux libc5 では、 5 つの C 標準のフラグと ' フラグ、ロケール、 "%m$" と "*m$" が使える。 また、長さ修飾子 h, l, L, Z, iand q が使えるが、 L と q は両方とも long double と long long int に対応している (これはバグである)。 現在では変換 F, D, O, U は認識されないが、変 換文字 m が追加された。これは strerror(errno) を出力するものである。 glibc 2.0 では、変換文字 C と S が追加された。 glibc 2.1 では、長さ修飾子 hh, j, t, z と変換文字 a, A が追加された。 glibc 2.2 では、 C99 で規定された意味での変換文字 F と フラグ文字 I が追加された。
注意
テキストを buf に追加するのに、軽率にも次のようなコードを使っているプログラムがある。 sprintf(buf, "%s some further text", buf); しかしながら、標準規格では、 sprintf(), snprintf(), vsprintf(), vsnprintf() の呼び出しにお いて、コピー元とコピー先のバッファが重なっていた場合の 結果は不定である、と明記されてい る。 使用する gcc(1) のバージョンや指定したコンパイラのオプション次第では、 上記のような呼 び出しで、期待した結果が得られ「ない」ことがある。 glibc の snprintf() と vsnprintf() の実装は、バージョン 2.1 以降は C99 標準に準拠してお り、 上記の通りの動作をする。 glibc 2.0.6 までは、出力が切り詰められた場合は -1 を返す。
バグ
sprintf() と vsprintf() は勝手に十分に長い文字列領域があると仮定するので、呼び出し側は 実際の領域からあふれないように注意しなければならない。 しかし、これを保証することが不可能 な場合が多い。 生成される文字列の長さはロケール依存であり、予測が難しいことに注意。 代わり に snprintf() と vsnprintf() (または asprintf(3) と vasprintf(3)) を使うこと。 Linux libc4.[45] には snprintf() はないが、 libbsd が提供されており、 その中には sprintf() と等価な (つまり size 引き数を無視する) snprintf() がある。 したがって、初期の libc4 で snprintf() を使うと、深刻なセキュリティ問題を引き起こすことがある。 printf(foo); のようなコードはしばしばバグを引き起こす。 なぜなら foo に % 文字が含まれてる かもしれないからである。 foo が信頼できないユーザー入力から作られている場合には、 その中に %n が含まれていることがあり、 printf() 呼び出し時にメモリへの書き込みが起こり、 セキュリ ティーホールを作ることになるかもしれない。
例
Pi を 5 桁で出力する。 #include <math.h> #include <stdio.h> fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0)); 日付と時間を "Sunday, July 3, 10:02" の形式で出力する。 (weekday と month は文字列へのポイ ンタである) #include <stdio.h> fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min); 日 - 月 - 年 の順序で表示を行う国も多い。 従って、国際版では書式で指定された順番で 引き数 を表示できなければならない。 #include <stdio.h> fprintf(stdout, format, weekday, month, day, hour, min); format はロケールに依存しており、引き数の順番を変えることもできる。 format が "%1$s, %3$d. %2$s, %4$d:%5$.2d\n" であれば、 "Sonntag, 3. Juli, 10:02" という結果になる。 十分に大きな文字列領域を確保して、そこにメッセージを格納するには (glibc 2.0 と glibc 2.1 の両方で正しく動作するコード): バージョン 2.0.6 より前の glibc で切り詰めが起こった場合、切り詰めは適切に処理されず、エ ラーとして扱われる。 #include <stdio.h> #include <stdlib.h> #include <stdarg.h> char * make_message(const char *fmt, ...) { int n; int size = 100; /* Guess we need no more than 100 bytes */ char *p, *np; va_list ap; if ((p = malloc(size)) == NULL) return NULL; while (1) { /* Try to print in the allocated space */ va_start(ap, fmt); n = vsnprintf(p, size, fmt, ap); va_end(ap); /* Check error code */ if (n < 0) return NULL; /* If that worked, return the string */ if (n < size) return p; /* Else try again with more space */ size = n + 1; /* Precisely what is needed */ if ((np = realloc (p, size)) == NULL) { free(p); return NULL; } else { p = np; } } }
関連項目
printf(1), asprintf(3), dprintf(3), scanf(3), setlocale(3), wcrtomb(3), wprintf(3), locale(5)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.54 の一部 である。プロジェクト の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。