はじめての C

データを 追加できるのが わかったので、次は 実際に ファイルに どれだけの 数の データが あるか 調べてみます。 ここでは、関数 fseek と ftell を 使います。 man page は 次の とおり、

名前  fseek, ftell - ストリームの 位置を 変更する

書式 #include

int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);

説明 fseek 関数は stream によって 指定された ストリームにおいて、
ファイル位置表示子 (file position indicator) を セットする。
新たな 位置 (バイト単位) は whence で 指定された 位置に
offset バイトを 加えることによって 与えられる。 whence が
SEEK_SET, SEEK_CUR, SEEK_END の どれかに なっている場合は、
それぞれ ファイルの 先頭、現在の 位置表示子、ファイルの 末尾
からの オフセットが 取られる。 fseek 関数の 呼び出しが 成功
すると、ストリームの end-of-file 表示子は クリアされ、それ
までに ungetc(3) 関数で 戻した データは なかったことになる。

ftell 関数は stream によって 指定された ストリームにおける、
ファイル位置表示子の 現時点での 値を 与える。

返り値 fseek は 成功すると 0 を 返す。 ftell は 現在の オフセットを
返す。

コードは、
#define SEEK_END 2

long last;
int record;

fseek(fp, 0L, SEEK_END);
last = ftell(fp);
record = (int)last / sizeof(PERSON);
fprintf(stdout, "Record: %d item%s.\n", record, record == 1 ? "" : "s");

fseek で fp (file positin) を ファイルの 最後に 移動、次に ファイルの 先頭から fp までの 値 = バイト数 (long) を 数えます。
最後に、バイト数を 構造体の 配列 PERSON の サイズで 割って、データの 数を 求めています (last が long 型なので、キャストで int に 変更)。


(追記) 改訂した プログラムが こちら ↓*1
/* addbook.c */
#include
#include "add_book.h"

#define SEEK_END 2

int main(int argc, char **argv)
{
PERSON add_book[MAX_PSN];
int c;

long last;
int record;

FILE *fp;

if (argc != 2) {
fprintf(stderr, "Usage: ./addbook [file]\n");
exit(1);
}
if )((fp = fopen(argv[1], "a+b"))( == NULL) {
fprintf(stderr, "Can't open %s.\n", argv[1]);
exit(2);
}
puts ("Press [ctrl + d] at the time of finish.");

for (c = 1; c < MAX_PSN; c++) {
puts("Enter the name.");
if (fgets(add_book[c].name, MAX_NAME, stdin) == 0)
break;
else {
puts("Now enter the postal code.");
fgets(add_book[c].postal_code, MAX_PC, stdin);
puts("Now enter the address.");
fgets(add_book[c].address, MAX_ADDR, stdin);
puts("Now enter the phone number.");
fgets(add_book[c].phone, MAX_PHN, stdin);

getchar();
}
}
if (c >= MAX_PSN)
fprintf(stderr, "The entry is over.\n");

fwrite(add_book + 1, sizeof(PERSON), c - 1, fp);

fseek(fp, 0L, SEEK_END);
last = ftell(fp);
record = (int)last / sizeof(PERSON);
fprintf(stdout, "Record: %d item%s.\n", record, record == 1 ? "" : "s");

fclose(fp);

return 0;
}

(追記) コードを 一部 訂正 (06/09/27)

*1:06.09.13