情報基礎演習II − 第14回


1.ファイル処理


ファイルを開く/閉じる

データの入出力を、 キーボードや画面に対して行う代わりに、 データファイルに対して行うことができます。 データファイルを扱うには、 次の3つのステップを経ます。
  1. データファイルを開く。
  2. データファイルに対して、データの入出力を行う。
  3. データファイルを閉じる。
data という名前のファイルから データを読み出す場合、 これは次のようなプログラムになります。
#include <stdio.h>

void func(void)
{
    FILE *fp;

    fp = fopen("data", "r"); /* data というデータファイルを開く */

    /* ここで data というデータファイルからデータを読み出す */

    fclose(fp); /* data というデータファイルを閉じる */
}
ここで fp/fopen/fclose は、次のような役割を持っています。
FILE *fp
fp は FILE 型のポインタ変数です。 ファイルポインタと呼ばれます。 変数ですから変数名は自分で決めてください。 FILE というデータ型は stdio.h で定義されています。 ファイルポインタは fopen などの戻り値として得られ、 データファイルへの読み書きはこの変数を介して行います。

fopen("data", "r")
データファイルを開きます。 戻り値として開いたファイルのファイルポインタを返します。 ファイルが開けなかったときは、NULL という記号定数 (これも stdio.h で定義されています)を返します。 一つ目の引数は開くファイルのパス名の文字列で、 二つ目の引数は開く「モード」を指定する文字列です。

"r"
読み出し用で開きます。
"w"
書き込み用で開きます。
"a"
ファイルの最後にデータを追加するように開きます。 書き込み用になります。
"r+"
読み書き両用に開きます。 ファイルは先頭の部分から読み書きします。
"w+"
読み書き両用に開きます。 既に存在したファイルの中身は消します。
"a+"
読み書き両用に開きます。 ファイルの最後の部分から読み書きします。

fclose(fp) ファイルポインタ fp で示された データファイルの読み書きを終了します。

ファイルの読み書き

実際にデータファイルにデータを書いたり、 データファイルからデータを読んだりするには、 fprintf/fscanf が使えます。 これは標準入出力(キーボード、画面)に対する 入出力に使う printf/scanf とほぼ同じで、 最初の引数(第1引数)にファイルポインタを指定します。
#include <stdio.h>

int main(void)
{
    FILE *fp; /* ファイルポインタ */
    int w, x, y, z; /* 書き込むデータ */

    /* ファイルを書き込み用に開く(この場合は新規作成になる)*/
    fp = fopen("data", "w");

    /* ファイルが開けなかったらメッセージを表示して、*/
    /* 終了ステータスを 1 にしてプログラムを終了する */
    if (fp == NULL) {
        printf("ファイルが開けませんでした\n");
        exit(1);
    }

    z = (y = (x = (w = 1) + 1) + 1) + 1;

    /* データを書き込む */
    fprintf(fp, "%d %d %d %d\n", w, x, y, z);

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

    return 0;
}
上のようなプログラムによって生成されたファイル data の内容は、 下のようなプログラムで読み出すことができます。
#include <stdio.h>

int main(void)
{
    FILE *fp; /* ファイルポインタ */
    int w, x, y, z; /* 読み出すデータ */

    /* ファイルを読み込み用に開く */
    fp = fopen("data", "r");

    /* ファイルが開けなかったらメッセージを表示して、*/
    /* 終了ステータスを 1 にしてプログラムを終了する */
    if (fp == NULL) {
        printf("ファイルが開けませんでした\n");
        exit(1);
    }

    /* データを読み出す */
    fscanf(fp, "%d %d %d %d", &w, &x, &y, &z);

    printf("%d %d %d %d\n", w, x, y, z);

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

    return 0;
}
なお、この例では変数の内容を fprintf で文字列に変換して 出力しているので、データファイル data はテキストファイル (画面表示可能な文字からなるファイル)になります。 cat コマンドや more、less などによって、 テキストファイルを画面で見ることができます。
% cat data

■課題62■

■課題63■


入力の繰り返し

データファイルから繰り返しデータを入力する場合、 データの終りに達した(それ以上データがない)ことを検出して、 データの入力を終わる必要があります。
#include <stdio.h>

int main(void)
{
    FILE *fp;
    int i, n;

    printf("データの数を入れてください: ");
    scanf("%d", &n);

    fp = fopen("data", "w");

    for (i = 1; i <= n; i++) {
        fprintf(fp, "%d\n", i);
    }

    fclose(fp);

    return 0;
}
上の例はキーボードから整数を入力し、 1からその数までの数をデータファイル data に保存します。 このようなプログラムによって作られたデータファイルから データを読み込むには、データをひとつ読む度にデータの終りを検査します。
#include <stdio.h>

int main(void)
{
    FILE *fp;
    int i, n = 0, sum = 0;

    fp = fopen("data", "r");

    if (fp == NULL) {
        printf("ファイルが開けません\n");
        exit(1);
    }

    while (fscanf(fp, "%d", &i) != EOF) {
        sum += i;
        n++;
    }

    fclose(fp);

    printf("データの数は %d 個でした\n", n);
    printf("データの合計は %d でした\n", sum);

    return 0;
}
scanf/fscanf は 戻り値として変換したデータの数を返します。 もし既にデータファイルの終りまで読み込んでいて、 それ以上入力するデータがなければ、 EOF という記号定数を返します(これも stdio.h で定義されています)。

また、feof を使えば、 入力の終りに達しているかどうかだけを調べることができます。

feof(fp)
ファイルポインタ fp が入力の終りに達していれば非0(真)、 達していなければ0(偽)を返します。

■課題64■