14. ライブラリ関数(7/36) - 入出力ライブラリ(6/10)
14.9 ファイルの終端及び、エラーの検出関数
入出力関数の多くはファイルの終端を検出すると、EOF(end of file)やNULLを返しますし、エラーを検出した場合も同じ値を返します。従って、本当にEOFなのかエラーなのか分かりません。そこで、厳密にEOFなのかエラーなのかを調べたいような場合に、ここで紹介する関数を使うとよいでしょう。
14.9.1 feof関数
feof関数はファイルポインタに対応したファイルのEOF(end of file)の状態を調べます。
【表14-1-25】 feof関数
形式 | #include <stdio.h>
int feof(FILE *fp); |
返り値 | EOFであれば0以外の値を返します。 |
引数 |
- FILE *fp
- EOFかどうかを調べるファイルのファイルポインタを指定します。
|
14.9.2 ferror関数
ferror関数はファイルポインタに対応したファイルのエラー状態を調べます。
【表14-1-26】 ferror関数
形式 | #include <stdio.h>
int ferror(FILE *fp); |
返り値 | エラーであれば0以外の値を返します。 |
引数 |
- FILE *fp
- エラーかどうかを調べるファイルのファイルポインタを指定します。
|
14.9.3 clearerr関数
clearerr関数はファイルポインタに対応したファイルのEOF(end of file)とエラーの状態をクリアします。
【表14-1-27】 clearerr関数
形式 | #include <stdio.h>
void clearerr(FILE *fp); |
返り値 | ありません。 |
引数 |
- FILE *fp
- クリアするファイルのファイルポインタを指定します。
|
使用法、 他 |
終端まで入力したファイルを、再度入力したいような場合にも使用できます。
|
14.9.4 例題
前ページの例題と同じく、下記のような番号・体重・身長・血液型のデータが登録されているex14_1_6.datファイルを入力して標準出力に編集出力します。
1,67,188,A
2,98,176.5,O
3,43.2,156.5,AB
4,55.5,167.5,B
5,75.7,166.5,A
#include <stdio.h>
int main(void)
{
FILE *fp;
char in_file[] = "./DATA/ex14_1_6.dat";
short int number; /* 番号 */
float weight; /* 体重 */
double height; /* 身長 */
char blood[4]; /* 血液型 */
int return_code = 0;
if((fp = fopen(in_file, "r")) != NULL)
{
printf("%-4s %-8s %-8s %s\n", "番号", "体重", "身長", "血液型");
while(1)
{
/* 番号、体重、身長、血液型を入力 */
fscanf(fp, "%hd,%f,%lf,%s",
&number, &weight, &height, blood);
/* EOFのチェック */
if(feof(fp) == 0)
{
printf(" %03hd %6.1f %6.1f %s\n",
number, weight, height, blood);
}
else
{
break; /* 入力終了。繰り返しから抜ける */
}
}
fclose(fp);
}
else
{
printf("%sがオープン出来ませんでした。", in_file);
return_code = 1;
}
return return_code;
}
$ ./ex14_1_8.prg
番号 体重 身長 血液型
001 67.0 188.0 A
002 98.0 176.5 O
003 43.2 156.5 AB
004 55.5 167.5 B
005 75.7 166.5 A
$
- 22行目
- feof関数でEOFかどうかを調べて、EOFでなかったら入力した値を表示します。
- 29行目
- EOFだったら入力のための繰り返しから抜け出します。
14.10 バイナリファイルの入出力関数
ファイルにはテキストファイルとバイナリファイルがありますが、今まで説明してきた関数はテキストファイルの入出力用でした。ここで説明するfread関数とfwrite関数はテキストファイルも取り扱えますが、主にバイナリファイルを取り扱う時に使用します。
14.10.1 fread関数
fread関数はファイルポインタに対応したファイルからレコード単位に入力します。入力データの変換は行いません。
【表14-1-28】 fread関数
形式 | #include <stdio.h>
size_t fread(void *buff, size_t rec_size, size_t rec_num, FILE *fp); |
返り値 | 入力したレコードの個数を返します。ファイルの終端(EOF)やエラーを検出した場合は引数で指定したレコード数より小さな値(または0)を返します。 |
引数 |
- void *buff
- 入力したデータを格納する領域を指定します。
- size_t rec_size
- レコード長をバイト単位で指定します。
- size_t rec_num
- 入力するレコードの個数を指定します。
- FILE *fp
- 入力するファイルのファイルポインタを指定します。
|
使用法、 他 |
返り値ではEOFかエラーなのかが明確ではありませんので、明確にしたい場合はeof関数やferror関数を使用します。
|
14.10.2 fwrite関数
fwrite関数はファイルポインタに対応したファイルにレコード単位に出力します。出力データの変換は行いません。
【表14-1-29】 fwrite関数
形式 | #include <stdio.h>
size_t fwrite(const void *buff, size_t rec_size, size_t rec_num, FILE *fp); |
返り値 | 出力したレコードの個数を返します。エラーを検出した場合は引数で指定したレコード数より小さな値(または0)を返します。 |
引数 |
- void *buff
- 出力するデータを格納してある領域を指定します。
- size_t rec_size
- レコード長をバイト単位で指定します。
- size_t rec_num
- 出力するレコードの個数を指定します。
- FILE *fp
- 出力するファイルのファイルポインタを指定します。
|
使用法、 他 |
返り値ではエラーが明確ではありませんので、明確にしたい場合はferror関数を使用します。
|
14.10.3 例題
下記のような番号・体重・身長・血液型のデータが登録されているex14_1_6.datファイルを入力して、バイナリのままex14_1_9_out.datファイルに出力します。
1,67,188,A
2,98,176.5,O
3,43.2,156.5,AB
4,55.5,167.5,B
5,75.7,166.5,A
#include <stdio.h>
/* 個人情報構造体 */
struct person_info {
int number; /* 番号 */
double weight; /* 体重 */
double height; /* 身長 */
char blood[4]; /* 血液型 */
};
int main(void)
{
FILE *fp_in;
char in_file[] = "./DATA/ex14_1_6.dat";
FILE *fp_out;
char out_file[] = "./DATA/ex14_1_9_out.dat";
struct person_info person;
int return_code = 0;
if((fp_in = fopen(in_file, "r")) != NULL)
{
if((fp_out = fopen(out_file, "w")) != NULL)
{
/* 番号、体重、身長、血液型を入力 */
while(fscanf(fp_in, "%d,%lf,%lf,%s*",
&person.number, &person.weight, &person.height, person.blood) != EOF)
{
/* personの内容を出力 */
fwrite(&person, sizeof(person), 1, fp_out);
}
fclose(fp_out);
}
else
{
printf("%sがオープン出来ませんでした。", out_file);
return_code = 1;
}
fclose(fp_in);
}
else
{
printf("%sがオープン出来ませんでした。", in_file);
return_code = 1;
}
return return_code;
}
$ ./ex14_1_9.prg
$
$ od -x -A x -w24 ./DATA/ex14_1_9_out.dat ← odコマンドで、ファイルの内容を十六進数で表示します。
000000 0001 0000 0000 0000 c000 4050 0000 0000 8000 4067 0041 0000
000018 0002 0000 0000 0000 8000 4058 0000 0000 1000 4066 004f 0000
000030 0003 0000 999a 9999 9999 4045 0000 0000 9000 4063 4241 0000
000048 0004 0000 0000 0000 c000 404b 0000 0000 f000 4064 0042 0000
000060 0005 0000 cccd cccc eccc 4052 0000 0000 d000 4064 0041 0000
000078
- 29行目
- person構造体変数の内容を、そのまま(編集しないで)fwrite関数で出力します。第2引数のsizeof(person)はsizeof演算子でperson構造体データの長さを求めています。(sizeof(person_info)でも同じです)