はじめての C

先月も チラッと 触れたけど、C を 学ぶ上で ネックと なるのは - ポインタは 別にして - データを プログラムに どう 取り込むか、と いうことです。
で、やっと わかった↓

UNIX (の データ) には テキストモードしか ない。

これだけです ...oLr
「基礎C言語」(isbn:4000078569) に 住所録の プログラムが あるので、それを 少し いじってみます (p275-278)。
使う 関数は fwrite (fread)。man page は 次の とおり。

名前  fread, fwrite - バイナリストリームの入出力

書式 #include
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

説明 fread 関数は stream ポインタで 指定された ストリームから nmemb 個の データ
を 読み込み、ptr で 与えられた 場所に 格納する。 個々の データは size
バイトの 長さを 持つ。
fwrite 関数は ptr で 指定された 場所から 得た nmemb 個の データを、stream
ポインタで 指定された ストリームに 書き込む。 個々の データは size バイト
の 長さを 持つ。

返り値 fread と fwrite は 読み書きに 成功した 要素の 個数を 返す。 エラーが 生
じた 場合や、end-of-file (ファイルの最後) に 達した 場合、返り値は 指定
した 個数よりも より 小さい 値 (または ゼロ) となる。
fread は end-of-file と エラーを 区別しないので、どちらが 生じたかを
判断するためには、呼び出し側で feof(3) と ferror(3) とを 使用しなければ
ならない。

早速、プログラムを 組み立てていきます。 データは 構造体の 配列に 入れています。
/* addbook.h */
#define MAX_NAME 50 + 1
#define MAX_PC 12 + 1
#define MAX_ADDR 100 + 1
#define MAX_PHN 12 + 1
#define MAX_PSN 300 + 1

typedef struct {
char name[MAX_NAME];
char postal_code[MAX_PC];
char address[MAX_ADDR];
char phone[MAX_PHN];
} PERSON;

/* addbook.c */
#include
#include "addbook.h"

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

FILE *fp;

if (argc != 2) {
fprintf(stderr, "Usage: ./addbook [file]\n");
exit(1);
}
if )((fp = fopen(argv[1], "wb"))( == 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");

/* heap_sort(add_book, c - 1) */

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

fclose(fp);

return 0;
}

この プログラムは まだ 完成していません。 このままだと、データを 上書きしてしまうのと、途中で コメントアウトしている、
/* heap_sort(add_book, c - 1); */
の 部分の 関数が できてないからです。 でも、コンパイルすれば ちゃんと? 動きますが ...
$ cc -o addbook addbook.c
$ ./addbook myaddbook
Press [ctrl + d] at the time of finish
Enter the name.
NANNO nanibei
Now enter the postal code.
111-1111
Now enter the address.
1-1-1 Nantoka, Kantoka
Now enter the phone.
111-1111-1111
Enter the name. (<- ctrl + d)
$ cat myaddbook
NANNO nanibei
111-1111
1-1-1 Nantoka, Kantoka
111-1111-1111 $
関数 fwrite, fread を 使えば、構造体などの データを ファイルに 書き入れたり 読みだしたりが できることと、(まだ してませんが) ファイルが 開いた 状態で、さまざまな アルゴリズムを 使って データを いじることが できる、ということですネ。
(追記) コードを 一部 訂正 (06/09/27)