C初級:ファイルから指定バイト数を読み取る(行単位の読み取り)/fgets関数

C言語初級カテゴリのロゴ画像 C言語初級

fgets関数を使うとファイルから指定バイト数のデータを読み取る、あるいは行単位にデータを読み取ることが可能です。
この記事ではfgets関数の基本的な使い方を紹介します。

上記の行単位の読み取りという言い方には少し語弊があります。
fgets関数は、基本的には引数に指定したバイト数を読み取ります。しかし途中に改行文字(\n)が含まれていた場合は、指定バイト数に満たなくても読み取りを終えてしまうため、fgets関数には行単位で読み取るというイメージがあります。

実際のサンプルで示します。

【基本】fgets関数の使い方サンプル

読み取るファイル: alpha.txt

ABCDE
FGHIJ
KLMNO
PQRST
UVWXY
Z

サンプル: file_fgets.c

/* ファイルから指定バイト読み取る */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	FILE *fp;
	char buffer[10];
	
	/* ファイルを開く */
	fp = fopen("alpha.txt", "r");
	if(fp == NULL){
		printf("ファイルが開けません\n");
		exit(1);
	}
	
	/* ファイルから指定バイト読み取る */
	fgets(buffer, 3, fp);
	printf("buffer = [%s]\n", buffer);

	/* ファイルを閉じる */
	fclose(fp);
	
	return 0;
}

実行結果

buffer = [AB]

解説

fgets関数の引数の指定方法は次の通りです。

fgets( 読み取り先, バイト数, ファイルポインタ );

第1引数: 読み取り先としてchar型配列へのポインタを指定します
第2引数: 読み取るバイト数int型で指定します
第3引数: fopen関数の戻り値であるファイルポインタを指定します

上記サンプルでは、ファイルから3バイト分のデータを変数bufferに読み取っています。

fgets(buffer, 3, fp);

しかし、表示結果を見ると先頭の2文字分しか表示されていません。

buffer = [AB]

これはfgets関数が第2引数に 指定した数-1 バイトしか読み取らないことを示します。これは読み取ったデータの最後に文字列の終わりを表すヌル文字(\0)を挿入するためです。

イメージ

ヌル文字を含めて指定バイト(上記の場合は3バイト)保存されている形です。
ですから、fgets関数の第2引数には 読み取りたいバイト数 +1を指定するようにします。

fgets関数は改行を読み取ると指定バイト数以下でも終了してしまう

fgets関数の特徴として、改行(\n)が読み込まれた場合、読み取りを終了する、という点が挙げられます。
例を示します。

file_fgets_cr.c

/* fgets関数は改行までを読み取る */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	FILE *fp;
	char buffer[10];
	
	/* ファイルを開く */
	fp = fopen("alpha.txt", "r");
	if(fp == NULL){
		printf("ファイルが開けません\n");
		exit(1);
	}
	
	/* ファイルから指定バイト読み取る */
	fgets(buffer, 10, fp);	/* 10バイト読み取り */
	printf("buffer = [%s]\n", buffer);

	/* ファイルを閉じる */
	fclose(fp);
	
	return 0;
}

実行結果

buffer = [ABCDE
]

ほとんど最初に紹介したプログラムと同じですが、fgets関数の第2引数の数値を増やし10(10バイト=半角10文字分)としました。

fgets(buffer, 10, fp); /* 10バイト読み取り */

ファイルの1行目は、 ABCDE の後、改行文字が保存されているため、10バイトには満たないですがそこで読み取りを終えています。

イメージで表すとこんな感じです。

実行結果が変だと思われたかもしれません。改行文字(\n)も1文字として読み込まれているためです。

変数bufferの中身はこうなっています。

ABCDE の後に改行文字(\n)があるため、printf(“buffer = [%s]\n”, buffer); を実行した際、表示としては E の後に改行が入る形となります。

buffer = [ABCDE ←ここで改行
]

【応用】fgets関数でファイルの内容を全て読み取るサンプル

fgets関数ではファイルの末尾(EOF)が読み込まれた場合、NULLを返します。(ちなみにファイル読み取りエラーの場合もNULLが返ります)

これを利用するとfgets関数を使ってファイルの内容を全て読み取るプログラムを作成できます。

file_fgets_null.c

/* fgets関数でファイルの内容を全て読み取る */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	FILE *fp;
	char buffer[256];
	
	/* ファイルを開く */
	fp = fopen("alpha.txt", "r");
	if(fp == NULL){
		printf("ファイルが開けません\n");
		exit(1);
	}
	
	/* ファイルの末尾(EOF)まで読み取る */
	while(fgets(buffer, 256, fp) != NULL){
		printf("%s", buffer);
	}

	/* ファイルを閉じる */
	fclose(fp);
	
	return 0;
}

実行結果

ABCDE
FGHIJ
KLMNO
PQRST
UVWXY
Z

上記プログラムは、fgets関数でファイル内容を全て読み取る定番の記述です。

また、fgets関数とは関係ありませんが、ファイルから1バイト読み取るfgetc関数と今回のfgets関数とでは、ファイルの末尾(EOF)が読み込まれた際の戻り値が違います。

紛らわしいので、まとめておくと

fgetc関数1バイトの文字を読み取り
戻り値:int型
ファイルの末尾が読み込まれるとEOFが返る
fgets関数指定バイト数の文字を読み取り
戻り値:char型ポインタ
ファイルの末尾としてEOFが読み込まれるとNULLが返る

となります。

以上、ファイルから指定バイト数を読み取る(行単位の読み取り)/fgets関数でした。

コメント

タイトルとURLをコピーしました