【C言語入門】fscanfの使い方

こんにちは、もがちゃんです

今回は、fgets と同様にファイルからの入力で使用する fscanf の使い方を、簡単なサンプルソースと一緒に説明したいと思います

fscanfの構文

#include <stdio.h>
int fscanf(FILE * restrict stream,
       const char * restrict format, ...);

fscanfの説明

fscanfは、streamで指定されたファイルポインタに紐づくファイルから、formatで指定された書式に応じて、実引数に変換した値を取得します

formatで指定する書式の数と、実引数の数および、forrmatで指定する変換方法と、実引数の型は、一致させる必要があります

実引数には、値を格納する変数のアドレスを指定します

fscanf関数は、formatによって指される文字列の制御に基づいてstreamが指すストリームから入力を読み取って変換し、formatに続く実引数の指すオブジェクトに代入する。formatが指す文字列は、許される入力の列とそれらの代入時の変換方法とを指定する書式とする。書式に対して実引数が不足しているときの動作は、未定義とする。実引数が残っているにもかかわらず書式が尽きてしまう場合、余分の実引数は、評価するだけで無視する。

JISX3010 プログラム言語C
stream

入力したいファイルに紐づくファイルポインタを指定します

(fopen関数の返却値を指定します)

format

書式は、0個以上の指令で構成され、指令は、1個以上の空白類文字(空白、水平タブ、改行、垂直タブおよび書式送り)、%や空白類文字でない通常の文字、または、変換指定で構成されます

各変換指定の先頭は、%で始まり、%の後ろには、以下の項目を順に指定します

  • 代入抑止文字の*(アスタリスク)(省略が可能)
  • 最大フィールド幅を指定する正の10進数(省略可能)
  • 変換後の値を代入するオブジェクトの大きさを指定する長さ修飾子(省略可能)
  • 適用する変換の種類を指定する変換指定子の文字
長さ
修飾子
意味
hhd,i,o,u,x,X又はn変換指定子が続く場合、対応する実引数の型が signed char 型又は unsigned char 型へのポインタ型であることを指定する
hd,i,o,u,x,X又はn変換指定子が続く場合、対応する実引数の型が short int 型又は unsigned short int 型へのポインタ型であることを指定する
l(エル)d,i,o,u,x,X又はn変換指定子が続く場合,対応する実引数の型が long int 型又は unsigned long int 型へのポインタ型であることを指定する
a,A,e,E,f,F,g又はG変換指定子が続く場合、対応する実引数の型がdouble型へのポインタ型であることを指定する
c,s又は[変換指定子が続く場合、対応する実引数の型が wchar_t 型へのポインタ型であることを指定する
ll(エルエル)d,i,o,u,x,X又はn変換指定子が続く場合、対応する実引数の型が long long int 型又は unsigned long long int 型へのポインタ型であることを指定する
jd,i,o,u,x,X又はn変換指定子が続く場合、対応する実引数の型が intmax_t 型又は uintmax_t 型へのポインタ型であることを指定する
zd,i,o,u,x,X又はn変換指定子が続く場合、対応する実引数の型が size_t 型又はそれに対応する符号付き整数型へのポインタ型であることを指定する
td,i,o,u,x,X又はn変換指定子が続く場合、対応する実引数の型が ptrdiff_t 型又はそれに対応する符号無し整数型へのポインタであることを指定する
La,A,e,E,f,F,g又はG変換指定子が続く場合、対応する実引数の型が long double 型へのポインタ型であることを指定する
長さ修飾子の種類と意味
変換指定子意味
d符号が省略可能な10進整数
対応する実引数は、符号付き整数型へのポインタでなければならない
i符号が省略可能な整数
対応する実引数は、符号付き整数型へのポインタでなければならない
o符号が省略可能な8進整数
対応する実引数は、符号無し整数型へのポインタでなければならない
u符号が省略可能な10進整数
対応する実引数は、符号無し整数型へのポインタでなければならない
x符号が省略可能な16進整数
対応する実引数は、符号無し整数型へのポインタでなければならない
a
e
f
g
符号が省略可能な浮動小数点数
対応する実引数は、浮動小数点型へのポインタでなければならない
cフィールド幅(この指令中にフィールド幅が存在しない場合,1とする。)で指定された長さの文字の並び
文字の並びすべてを受け取れる大きさをもつ文字型配列の先頭要素へのポインタでなければならない
NULL文字は付加しない
s非空白類文字の並び
対応する実引数は、文字の並びすべて及び自動的に付加される終端NULL文字を受け取れる大きさをもつ文字型配列の先頭要素へのポインタでなければならない
[期待される文字集合[走査文字集合(scanset)]の要素の文字の空でない並び
対応する実引数は、文字の並びすべて及び自動的に付加される終端NULL文字を受け取れる大きさをもつ文字型配列の先頭要素へのポインタでなければならない
p処理系定義の文字の並びの集合(fprintf関数の%p変換が生成する文字の並びの集合と同じ)
対応する実引数は、voidへのポインタのポインタでなければならない
n入力を読み取らない
fscanf関数の呼出しでその時点までに入力ストリームから読み取った文字数を、実引数に書き込む
対応する実引数は、符号付き整数型へのポインタでなければならない
%一つの%と照合する、変換も代入も行わない
この変換指定全体は、%%でなければならない
変換指定子の種類と意味
返却値

ファイルからの入力変換に
成功した場合は、代入された入力項目の個数を返します

失敗した場合は、マクロEOFの値を返します

変換が一つも行われないまま入力誤りが発生した場合、fscanf関数は、マクロEOFの値を返す
その他の場合、fscanf関数は、代入された入力項目の個数を返す

JISX3010 プログラム言語C

fscanfの使い方サンプル

fscanfを使ったサンプルソースと実行結果を紹介します

入力ファイル
%%%1  11	12	13	abcdefg
21	22	23	ABCDEFG

ソースコードと実行結果
#include <stdio.h>

/*
 * scanfのサンプル
 */
int main(int argc, char *argv[]) {
  FILE *fp = NULL;

  fp = fopen("input.txt","r");
  if(fp == NULL) {
    fprintf(stdout, "fopen エラー\n");
    return -1;
  }

  //-----------------------------------
  // 変換指定子%とsのサンプル
  //-----------------------------------
  {
    int n = 0;
    char d[256] = {'\0'};
    fprintf(stdout, "example1(format文字%%%%%%s)");
    n = fscanf(fp, "%%%s", d);
    fprintf(stdout, "\t d[%s] n = %d\n", d, n);
  }
  //-----------------------------------
  // 長さ修飾子lと変換指定子dのサンプル
  //-----------------------------------
  {
    int n = 0;
    long d = -1;
    fprintf(stdout, "example2(format文字%%ld)");
    n = fscanf(fp, "%ld", &d);
    fprintf(stdout, "\td[%ld] n = %d\n", d, n);
  }
  //-----------------------------------
  // 最大フィールド幅指定と変換指定子dのサンプル
  //-----------------------------------
  {
    int n = 0;
    int d = -1;
    fprintf(stdout, "example3(format文字%%1d)");
    n = fscanf(fp, "%1d", &d);
    fprintf(stdout, "\td[%d] n = %d\n", d, n);
  }
  //-----------------------------------
  // 複数の変換指定子を指定したサンプル
  //-----------------------------------
  {
    int n = 0;
    int d1 = -1;
    long d2 = -1;
    char d3[256] = {'\0'};
    fprintf(stdout, "example4(format文字%%1d %%ld %%s)");
    n = fscanf(fp, "%1d %ld %s", &d1, &d2, d3);
    fprintf(stdout, "\td1[%d], d2[%ld], d3[%s] n = %d\n", d1, d2, d3, n);
  }
  //-----------------------------------
  // 変換指定子[を使用したサンプル(該当なし)
  //-----------------------------------
  {
    int n = 0;
    char d1[256] = {'\0'};
    char d2[256] = {'\0'};
    long d3 = -1;
    fprintf(stdout, "example5(format文字%%s %%[345] %%ld)");
    // %[345] の部分は、3 4 5の文字以外だと代入されない
    n = fscanf(fp, "%s %[345] %ld", d1, d2, &d3);
    fprintf(stdout, "\td1[%s], d2[%s], d3[%ld] n = %d\n", d1, d2, d3, n);
  }
  //-----------------------------------
  // 変換指定子[
(該当文字あり)
  // 代入抑止文字*
、変換指定子nを使ったサンプル
  //-----------------------------------
  {
    int n = 0;
    char d1[256] = {'\0'};
    long d2 = -1;
    char d3[256] = {'\0'};
    int  d4 = -1;
    fprintf(stdout, "example6(format文字%%[2] %%*d %%3s %%n)");
    // %*d の部分に対応する 実引数は、*は、代入抑止文字なので不要
    n = fscanf(fp, "%[2] %*d %3s %n", d1, d3, &d4);
    fprintf(stdout, "\td1[%s], d2[%ld], d3[%s], d4[%d] n = %d\n", d1, d2, d3, d4, n);
  }
  //-----------------------------------

  if(fp != NULL) {
    if(fclose(fp) != 0){
      fprintf(stdout, "fclose エラー\n");
      return -3;
    }
  }
}
fscanfを使ったサンプルソースの実行結果
fscanfを使ったサンプルソースの実行結果

fscanfのまとめ

実引数には、値を格納する変数・領域のアドレス(ポインタ)を指定する必要があります

streamにstdin(標準入力)を指定すると、scanfと同じ動作になります

fscanfは、ファイルの内容を変換して取得できるのは便利なのですが、変換に失敗した場合は、値を取得することが出来ないので、ファイルの内容が確実にformatで指定する形式に合っていないと、思ったような結果が得られないので注意が必要です

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA