この関数の目的
fscanf()は、ストリームからフォーマットされた文字列を取得する。
定義
#include <stdio.h> int fscanf(FILE *stream, const char *format, ...);
働き
この関数は、 stream に指されるストリームから入力を読み込む。 format に指される文字列は、読み込むことのできる入力のパターンや、入力をどのように変換するかを制御する。 後ろの引数は変換された入力の置き場所へのポインタとして使われる。引数が不足していた場合の動作は未定義である。 引数が残っているのに format が終わってしまった場合、余計な引数は(例によって)評価されるが、その他の意味では無視される。
フォーマットは複バイト文字の連なりで、シフト状態は最初と最後で一致していなければならない。
フォーマットは以下のような0個以上の「指令」と呼ばれる単位から成る。指令は1つ以上の空白、 %
か空白以外の普通の複バイト文字、変換指定のいずれかである。
変換指定は %
で始まり、以下の文字が順番に現れる。
*
の文字。
h
、 l
、 L
の文字。
d
、 i
、 n
の変換指定子は h
を付加すると int ではなく short int へのポインタを引数にとらねばならない。
同様に、 o
、 u
、 x
の変換指定子は h
を付加すると unsigned int ではなく unsigned short int へのポインタを、また l
を付加すると unsigned long int へのポインタを引数にとらねばならない。
e
、 f
、 g
の変換指定子は l
を付加すると float ではなく double へのポインタを、また L
を付加すると long double へのポインタを引数にとらねばならない。
h
、 l
、 L
が他の変換指定子に付加されたときの動作は未定義である。
fscanf 関数は各々の指令を順番に実行する。指令が失敗したら、関数は返る。失敗には(入力文字が無いことによる)入力の失敗と、合致の失敗がある。
空白文字から成る指令は、入力の最初の空白で無い文字か終わりまで読み進めることで実行される。
通常の複バイト文字からなる指令は、次の文字まで入力を読み進めることで実行される。もし文字が指令の表すものと異なっていた場合、指令は失敗し、その文字から後は読まれない。
変換指定子である指令は、指定子ごとに適合する入力の文字列の集合を後述のように定義する。変換指定子は以下のような順番で実行される。
まず、指定子の文字列に [
, c
, n
が入っていなければ、入力の空白文字( isspace 関数で特定される)は飛ばされる。
入力アイテムは、指令が n
指定子を含むまでストリームから読み込まれる。入力アイテムは文字数が最も多く合致する入力文字列の連続部分として定義されるが、次の場合は除く。
フィールド幅に達した場合、合致する部分の最初から数えてその長さまでの部分として定義される。入力アイテムの後ろの一文字は(あれば)読まれない。
入力アイテムの長さが0だった場合、指令の実行は失敗し、この場合はエラーによって入力を読むことができなくなる入力の失敗で無い限り、合致の失敗として扱われる。
% 指定子の場合を除いて、入力アイテムは変換指定子に適した型に変換される。入力アイテムが合致しなかった場合、指令の実行は失敗し、合致のエラーとなる。 代入を抑止する * の文字が指示されなければ、変換の結果は、関数への引数リストのうちまだ値を受け取っていない最初の実引数が指すオブジェクトに格納される。 オブジェクトの型が適切でない場合か、変換の結果が型の空間では表現できないものであった場合の動作は未定義である。
次の変換指定子は有効である。
d | base 引数に 10 を指定した strtol 関数の主体に期待されるのと同じ書式の、符号がついていてもよい十進整数に合致する。対応する引数は整数へのポインタでなくてはならない。 |
i | base 引数に 0 を指定した strtol 関数の主体に期待されるのと同じ書式の、符号がついていてもよい整数に合致する。対応する引数は整数へのポインタでなくてはならない。 |
o | base 引数に 8 を指定した strtoul 関数の主体に期待されるのと同じ書式の、符号がついていてもよい八進整数に合致する。対応する引数は無符号整数へのポインタでなくてはならない。 |
u | base 引数に 10 を指定した strtoul 関数の主体に期待されるのと同じ書式の、符号がついていてもよい十進整数に合致する。対応する引数は無符号整数へのポインタでなくてはならない。 |
x | base 引数に 16 を指定した strtoul 関数の主体に期待されるのと同じ書式の、符号がついていてもよい十六進整数に合致する。対応する引数は無符号整数へのポインタでなくてはならない。 |
e,f,g | strtod 関数の主体に期待されるのと同じ書式の、浮動小数点数に合致する。対応する引数は浮動小数点数へのポインタでなくてはならない。 |
s | 空白文字でない連続部分に合致する。対応する引数は部分文字列と付加される終端のヌル文字を受け入れるのに充分長い文字の配列の先頭要素へのポインタでなければならない。 |
[ | 長さがゼロでない、予期される文字の集合(スキャンセットと呼ばれる)の内の文字の連続に合致する。対応する引数は部分文字列と付加される終端のヌル文字を受け入れるのに充分長い文字の配列の先頭要素へのポインタでなければならない。変換指定子は、 format 文字列の中に続く文字を、対応する右角括弧( ] )まで含む。角括弧の中の文字(スキャンリスト)によってスキャンセットは構成される。ただし、左括弧の次の文字が ^ であった場合、スキャンセットは ^ と右括弧の間のスキャンリストに現れない文字となる。変換指定子が [] か [^] で始まる場合、右角括弧はスキャンリストの一部であり、次に出現する右角括弧が終わりを示し、それ以外の始まりかたなら最初の右括弧で定義が終わる。 - の文字がスキャンリストに現れ、先頭でない(最初の文字が ^ の場合は二番目でない)か、最後の文字でない時の動作は処理系定義である。 |
c | フィールド幅で指定される数(指定されなければ 1 )の文字の連続に合致する。対応する引数は文字列を受け入れるのに充分長い文字の配列の先頭要素へのポインタでなければならない。ヌル文字は付加されない。 |
p | fprintf 関数の %p 変換により生成されるものと同じ、処理系定義の連続部分の集合に合致する。対応する引数は void へのポインタのポインタでなければならない。入力アイテムの解釈は処理系定義である。入力アイテムがプログラムの実行中に、先に変換された値であったならば、結果のポインタはその値と等しくならなければならない。その他の場合の %p 指定子の動作は未定義である。 |
n | 入力は読まれない。対応する引数は関数呼び出しで読み込まれた文字数を格納する整数へのポインタでなければならない。 %n 指令の実行は fscanf 関数の終了と共に返される代入数には加えられない。 |
% | 一つの % に合致し、変換や代入は行われない。変換指定子の全体は %% と書かれなければならない。 |
変換指定子が有効でない場合の動作は未定義である。
E
、 G
、 X
の変換指定子は有効であり、それぞれ e
、 g
、 x
と等価の動作をする。
ファイルの終わりが入力中に現れた場合、変換は終了する。現在の指令と合致する(先頭の空白文字を除く)どの文字も出現する前にファイルの終わりが出現した場合、現在の指令は入力の失敗に終わる。そうでなければ、現在の指令の実行が合致の失敗として終わった場合、(あれば)続く指令は入力の失敗で終わる。
変換が合致しない入力文字で終わった場合、問題の文字は読まれずに入力ストリームに残される。続く空白文字(改行文字を含む)は指令に合致しない限り読まれずに残る。完全な合致の成功と中断された代入の区別は、 %n
指令の他に知ることはできない。
返り値は、どの変換よりも前に入力の失敗が発生した場合は、 EOF
マクロの値である。そうでなければ、指定したのよりも少ないか、初期の合致の失敗ならゼロの、代入された入力アイテムの数である。
解説
printf() 、または fprintf() と好対照を成している関数であるが、そのために誤解も多い。まず何よりも先に気をつけるべきは、この関数はポインタを引数にとるということである。 例えば、次のような使い方が一般的である。
int i; double d; char c; scanf("%d %lf %c", &i, &d, &c); printf("%d %lf %c", i, d, c);
scanf() はポインタをやる前に初心者向けに出てくることが多いので、 i
、
d
、 c
の前のアンパサントは「おまじない」(?)ということで教えることが多いのだが、関数は、
呼び出し元の変数を直接変える事はできないということをこの時点で知っても良い。
だから読み込んだ値を呼び出し元の変数に格納するには、その変数へのポインタを渡すことが必要になる。
これに対し fprintf() 系の関数は呼び出し元の変数を変える必要が無いのでポインタを引数にとらないのである。
このことに加え、可変長引数の標準変換が事をややこしくしている。 fprintf() の %f
と %lf
は double に、
&Lf
は long double に対応しているのだが、 scanf() の %f
は float へのポインタに、 %lf
は double へのポインタに、
%Lf
は long double へのポインタに対応しているのである。だから、これを例えば
scanf("%d %lf %c", &i, &d, &c); printf("%d %f %c", i, d, c);
という風にしても動く。
これは可変長引数に float は渡せないが float へのポインタは渡せるという事情( va_arg マクロの解説を参照)から来た仕様の非対称性である。
%hd
、 %d
についても同じ事が言えるが、バイトオーダーがビッグエンディアンのマシンでは short int に int を誤って格納しようとしたとき、
値の範囲内なら正しく数値が入るので気付きにくい(からといって安全なわけではないことに注意)し、そもそも scanf 、 printf 系の関数に short int を使うこと自体が皆無に近い。