この関数の目的
fprintf()は、ストリームにフォーマットされた文字列を出力する。
定義
#include <stdio.h> int fprintf(FILE *stream, const char *format, ...);
働き
この関数は stream で指定されるストリームに出力を行う。 format は以後に続く引数がどのように出力へ変換されるかを制御する。引数が不足していた場合の動作は未定義である。 引数が残っているのに format が終わってしまった場合、余計な引数はいつも通りに評価されるが、無視される。 この関数は format が終点に至った時点で返る。
フォーマットは複バイト文字の連なりで、シフト状態は最初と最後で一致していなければならない。 フォーマットは以下のような0個以上の「指令」と呼ばれる単位から成る。 '%'以外の普通の複バイト文字はそのまま転送される指令である。 '%'で始まる数文字は変換指定と呼ばれる指令で、以下のような文字が順番に'%'に続く。
# | 「代わりの形」に変換されるように指定するフラグ。変換指定子が c, d, i, n, p, s, u の指令では何の効力も持たない。 o 変換では、'0'が変換された文字列の先頭文字になるように精度が増やされる。精度がもともと'0'を先頭にするようなものなら、無視される。 x, X 変換では数字の先頭に "0x" または "0X" を付けた形になる。 e, E, f, g, G 変換ではいつでも小数点をつけるようになる(普通は必要ない小数点は省略される)。 g, G 変換では小数点以下の必要ない'0'も出力する(普通はしない)。 |
0 | ゼロ詰めを指定するフラグ。 u 以外の全ての変換において、左側に余った空白は全て'0'になる。 d, i, o, u, x, X変換では精度が指定されていれば'0'は無視される。 |
(空白) | 符号付き変換において、正の値のとき左側に1文字空白をあける。 |
+ | unsigned int 型の引数が符号なし8進数(o)、符号なし10進数(u)、符号なし16進数(xかX)で dddd の形に変換される。16進数表現では、 x では abcdef を使い、 X では ABCDEF を使う。精度は表示される最小の桁数を決める。変換された数字がこの桁数より少なくても表示できる場合、0が先頭に詰められる。精度は既定で1である。数値0を精度0で変換した場合、何の文字にもならない。 |
- | 左詰めを指定するフラグ。 u 以外の全ての変換において、変換文字列を右側に置いて左側を空白や'0'で埋めたりする代わりに、文字列を左側に置いて右側を空白で埋める。 |
d, i | int 型の引数が符号付き10進数で [-]dddd の形に変換される。精度は表示される最小の桁数を決める。変換された数字がこの桁数より少なくても表示できる場合、0が先頭に詰められる。精度は既定で1である。数値0を精度0で変換した場合、何の文字にもならない。 |
o, u, x, X | unsigned int 型の引数が符号なし8進数(o)、符号なし10進数(u)、符号なし16進数(xかX)で dddd の形に変換される。16進数表現では、 x では abcdef を使い、 X では ABCDEF を使う。精度は表示される最小の桁数を決める。変換された数字がこの桁数より少なくても表示できる場合、0が先頭に詰められる。精度は既定で1である。数値0を精度0で変換した場合、何の文字にもならない。 |
f | doule 型の引数が10進数で [-]dddd.ddd の形に変換される。小数点の後の桁数は精度によって指定されるとおりである。精度指定がないとき、この桁数は6となる。精度が0で'#'フラグが指定されないなら、小数点は現れない。小数点が現れるなら、1桁以上の数字が小数点より前に現れる。値は桁数に収まるように丸められる。 |
e, E | doule 型の引数が10進数で [-]d.ddde[+-]dd の形に小数点以上1桁になるように変換される。ここで小数点以上は、引数が 0 でなければ 0 でない1桁の数である。小数点の後の桁数は精度によって指定されるとおりである。精度指定がないとき、この桁数は6となる。精度が0で'#'フラグが指定されないなら、小数点は現れない。値は桁数に収まるように丸められる。 E 変換では指数部を表すのに 'e' の代わりに 'E' を使う。指数部は2桁以上である。値が 0 なら、指数部も 0 である。 |
g, G | doule 型の引数に f か e (または G なら E ) の変換をする。精度は重要な桁数を決める。精度が 0 なら、 1 として扱われる。使われる変換は、値によって以下のように決まる。指数部が -4 より小さくなるか、精度以上のときは e または E の変換が使われる。必要ない小数部分の'0'は削除される。小数部がなければ小数点は現れない。 |
c | int 型の引数が unsigned char 型に変換されたものが出力される。 |
s | 文字型の配列へのポインタ型の引数を使い、配列のヌル文字まで文字を出力する。精度が指定されれば、それ以上の長さに渡って出力することはない。精度が指定されていないか、文字型の配列の長さより大きかった場合、配列はヌル文字を含まなければならない。 |
p | void 型へのポインタ型の引数が、処理系定義の方法によって出力される。 |
n | int 型へのポインタ型の引数にこれまでに出力された文字数を書く。引数は出力されない。 |
% | '%' が出力される。全体としては"%%" と書かれなければならない。 |
変換の指定が不正だった場合の動作は未定義である。
引数に共用体や集合体やそれらへのポインタがあった場合の動作は未定義である。
フィールド幅が指定されなかったり、小さかったりしても、表示が切り詰められることはない。 幅は変換の結果に合わせて広げられる。
返り値は、出力した文字数である。エラーが発生した場合、負の数を返す。
解説
fprintf() は、 printf() の一般的なもので、 出力ストリームに文字列をフォーマットに従って出力する機能を持つが、これは例えば puts() などと違う。
変換指定子の定義は、上を読んでもらえれば余すところなく書いてあるはずであるが、なかなか読む気も起こるまい。 こちらにフォーマット指定子をまとめたページがあるので、参照されたい。 ここではいくつかサンプルをお見せしようと思う。コメントの内部は Mingw GCC での出力結果である。
#include <stdio.h> void main(){ int i; printf("%d\n", 200); /* 200 */ printf("%i\n", 200); /* 200 */ printf("% d\n", 200); /* 200 */ printf("% d\n", -200); /* -200 */ printf("%+d\n", 200); /* +200 */ printf("%+d\n", -200); /* -200 */ printf("%o\n", 200); /* 310 */ printf("%#o\n", 200); /* 0310 */ printf("%x", 200); /* c8 */ printf("%#x", 200); /* 0xc8 */ printf("%#X\n", 200); /* 0XC8 */ printf("%f\n", 123.456); /* 123.456000 */ printf("%10.2f\n", 123.456); /* 123.46 */ printf("%010.2f\n", 123.456); /* 0000123.46 */ printf("%e\n", 123.456); /* 1.234500e+02 */ printf("%E\n", 123.456); /* 1.234500E+02 */ printf("%10.3e\n", 123.456); /* 1.235e+02 */ printf("%g\n", 123.456); /* 123.456 */ printf("%g\n", 0.0000123456); /* 1.23456e-05 */ printf("[%c]\n", 'h'); /* [h] */ printf("[%*c]\n", 5, 'h'); /* [ h] */ printf("This is a %s.\n", "string"); /* This is a string. */ printf("[%s]\n", "overlength"); /* [overlength] */ printf("[%*s]\n", 5, "overlength"); /* [overlength] */ printf("[%.*s]\n", 5, "overlength"); /* [overl] */ printf("Address: %p\n", main); /* Address: 00401330 */ printf("this many of chars are written so far:%n", &i); printf("%d\n", i); /* this many of chars are written so far:38 */ }
最後の2つに注意していただきたいのだが、 p 変換では、何文字出力されるか、どんな表現方法かなどといった事は完全に処理系定義であるから、 ここの結果を信用しないでいただきたい。また、 n 変換では
printf("this many of chars are written so far:%n%d\n", &i, i);
というような書き方をしてしまうと、でたらめな出力になるだろう。 i の値は関数呼び出し時のもののコピーであり、関数内部で i の値が変更されたとしても、コピーのほうには反映されないからである。 よしんば反映されたとしても、変更される順番は未定義なので、最初の例のような結果が得られるかどうかは処理系によることになる。
フラグ(flag:旗)というのはコンピュータ用語で、オン・オフ二つの状態を取りうる変数のことを呼ぶ。
この場合のフラグは、それに対応する文字 "#0 -+"
を書くか書かないかでオン・オフが決まる。
この関数は可変長引数関数 (Variable argument) と呼ばれる特殊な関数である。
この種の関数は宣言の引数リストの最後に「...
」がついているもので、ここから後はどんな型のいくつの変数であろうと渡すことができる。
しかし、渡される側はどんな型のいくつの変数が渡されたかを直接知る手段はない。関数は format に渡される文字列を元に、これらの引数の数と型を知る。
よって、 format の文字列と実引数リストが食い違っていてはいけない。
変数のサイズを指定する h
、 l
、 L
については若干の注意が必要である。
%hd
は short int 、 %d
は int 、 %ld
は long int の引数に対応し、 %f
は float 、
%lf
は double 、 %Lf
は long double に対応しているのだが、可変長の引数には標準変換がなされ、
int より短い整数は int に、 double より短い浮動小数点数は double に暗黙のうちに変換されるため、 %hd
と %d
、
%f
と %lf
は同じ意味になってしまう。
これは fscanf() の仕様と非対称である。
標準変換については va_arg マクロの解説を参照されたい。
可変長引数関数については、 <stdarg.h> を参照されたい。