C 言語で fscanf を使ってファイルを一行ずつ読む
この記事では、C 言語で fscanf
を使ってファイルを一行ずつ読み込む方法をいくつか説明します。
関数 fscanf
を使って C 言語でファイルを一行ずつ読み込む
関数 fscanf
は C 標準ライブラリのフォーマット付き入力ユーティリティの一部です。異なる入力ソースに対して複数の関数が提供されており、例えば stdin
から読み込むための scanf
や文字列から読み込むための sscanf
、FILE
ポインタストリームから読み込むための fscanf
などがあります。後者は通常のファイルを一行ずつ読み込んでバッファに格納するために用いることができます。
fscanf
は printf
と同様の書式指定を受け付けるが、その詳細はこのページ にあります。以下の例では、fopen
関数呼び出しを用いてサンプル入力ファイルを開き、ファイルサイズいっぱいのメモリを確保して読み込みストリームを格納しています。"%[^\n] "
フォーマット文字列を指定して、改行文字が見つかるまでファイルストリームを読み込む。fscanf
は入力が終了すると EOF
を返すので、while
ループを使って一行ずつ繰り返して出力します。
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
const char *filename = "input.txt";
int main(int argc, char *argv[]) {
FILE *in_file = fopen(filename, "r");
struct stat sb;
stat(filename, &sb);
char *file_contents = malloc(sb.st_size);
while (fscanf(in_file, "%[^\n] ", file_contents) != EOF) {
printf("> %s\n", file_contents);
}
fclose(in_file);
exit(EXIT_SUCCESS);
}
出力:
> Temporary string to be written to file
前述のコードでは、入力ファイル名がファイルシステムに存在する場合は正常に実行される可能性が高いですが、複数回の関数呼び出しが失敗してプログラムが異常終了することがあることに注意してください。次のコード例は、エラーチェックルーチンを実装した修正版です。
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
const char *filename = "input.txt";
int main(int argc, char *argv[]) {
FILE *in_file = fopen(filename, "r");
if (!in_file) {
perror("fopen");
exit(EXIT_FAILURE);
}
struct stat sb;
if (stat(filename, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
char *file_contents = malloc(sb.st_size);
while (fscanf(in_file, "%[^\n] ", file_contents) != EOF) {
printf("> %s\n", file_contents);
}
fclose(in_file);
exit(EXIT_SUCCESS);
}
出力:
> Temporary string to be written to file
関数 fscanf
を用いて C 言語でファイルを一字一句読み取る
fscanf
関数を利用するもう一つの有用なケースは、ファイルを辿ってスペースで区切られたトークンをすべて解析することです。先ほどの例から変更すべき点は、フォーマット指定子を "%[^\n ] "
に変更することだけであることに注意してください。システムコールの stat
はファイルサイズを取得し、その値を malloc
引数に渡してバッファを確保します。この方法はシナリオによっては無駄かもしれませんが、最大の一行ファイルでもバッファに格納できることを保証します。
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
const char *filename = "input.txt";
int main(int argc, char *argv[]) {
FILE *in_file = fopen(filename, "r");
if (!in_file) {
perror("fopen");
exit(EXIT_FAILURE);
}
struct stat sb;
if (stat(filename, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
char *file_contents = malloc(sb.st_size);
while (fscanf(in_file, "%[^\n ] ", file_contents) != EOF) {
printf("> %s\n", file_contents);
}
fclose(in_file);
exit(EXIT_SUCCESS);
}
出力:
> Temporary
> string
> to
> be
> written
> to
> file