サイトマップ / C言語講座出入り口総目次目次:ファイル>ランダムアクセスファイル

青い直線

ランダムアクセスファイル

青い直線

[ユニークなファイル名で開く]←このソース→[空白文字の出現頻度]

/* ランダムアクセス */

/* 今日は、レコードの長さが一定の多数のデータを、書き込み用に開いたファイルに出力し、そのファイルを入力用として再度開き、レコード番号を入力して、その内容を画面に表示させます。つまり、ランダムアクセスファイルを作製し、データへのランダムアクセスを行います。ランダムアクセスを行うには、データの長さが一定の方が、容易です。

fseek( ) は、ファイルポインタで示されるファイル内で、次に読み込みあるいは書き込みを始める場所 ( ストリーム ) を指定します。

    #include <stdio.h>
    int  fseek(FILE *fp, long int offset, int where);

    例:err = fseek(fp, offset, where);

    実行結果        戻り値
    成功            0
    失敗            0 以外の数

where で、次に読み込みあるいは書き込みを始める場所を指定します。

    SEEK_SET    ファイルの先頭から
    SEEK_CUR    現在の位置から
    SEEK_END    ファイルの最後から

上記の値は <stdio.h> の中で定義されています。offset には、where で指定した位置からの距離をバイト単位で指定します。

freopen( ) は、filename で指定されたファイルを開きます。fopen( ) に似ていますが、もし、指定のファイルが開いていたら、一旦閉じてから、開きます。mode の指定の仕方は、fopen( ) と同じです。

    #include <stdio.h>
    FILE  *freopen(const char *filename, const char *mode, FILE *fp);

    例:newfp = freopen(filename, mode, oldfp);

    実行結果        戻り値
    成功            filename へのファイルポインタ
    失敗            NULL

ソースプログラムの説明

今回のソースプログラムでは、"w" モード ( 新しいテキストファイルを出力モードで開く ) を、"r" ( テキストファイルを入力モードで開く ) に変更しています。

今回使っている乱数のシードを設定する関数 SetSeed( ) と、乱数を発生する関数 GetRand( ) につきましては、このファイル を参照して下さい。ただし、 GetRand( ) は少し改造してあり、最大値で、引数 max までの正の整数を返す点が異なっています。

メインルーチンの中で、長さ LEN_ITEM_NAME の無意味なアルファベットの文字列を作り、それを name[ ] にしまいます。

    name[j] = 'a' + GetRand(26);

上記のコードにより、name[ ] の j 番目の要素に、'a' から 'z' のどれかの文字が入ります。26 はアルファベットの文字数です。レコード番号と、上記の無意味な文字列と、0 から MAX_PRISE までのint 型の乱数 prise を、一つのレコードとしてファイルに書き込みます。書き込むデータの総数は MAX_ITEM 個です。書き込みに使う書式文字列は、読み込みにも使います。

最後に入力モードでファイルをリオープンし、レコードにレコード番号でランダムアクセスし、レコードの内容を表示します。数字以外を入力するとループから抜けます。 */

/* ここからソースプログラム */

#include <stdio.h>
#include <time.h>            /* clock(  ) で必要 */
#include <stdlib.h>          /* exit(  ) で必要 */

#define MUL 12345            /* 乱数の発生に使用 */
#define INC 54321
#define MOD 65535

#define LEN_ITEM_NAME 2      /* 無意味な文字列の長さ */
#define MAX_PRISE 1000       /* 乱数の最大値 */
#define MAX_ITEM 60          /* ファイルに書き込むレコードの数 */
#define REC_SIZE 30L         /* 1 レコードのサイズ */

void SetSeed(void);
int GetRand(int max);
void main(void);

static unsigned int seed;

  /* 乱数のシードを設定 */
void SetSeed(void)
{
    seed = (unsigned  int)(clock(  ) % MOD );
}

  /* 最大値 max までの正の乱数を発生させる */
int GetRand(int max)
{
    seed = (MUL * seed + INC) % MOD;
    return (seed % max);
}

void main(void)
{
    int number;                             /* レコード番号 */
    char name[LEN_ITEM_NAME];               /* 無意味な文字列をしまう */
    int prise;                              /* 乱数をしまう */
    const char *format = "%2d  %20s  %4d";  /* 書式文字列 */
    long n;
    char *filename = "itemdata.txt";
    FILE *fp;
    int i, j;

      /* ファイルを出力モードで開く */
    if ((fp = fopen(filename,  "w")) == NULL) {
        fprintf(stderr, "ファイルを出力モードで開くのに失敗しました!\n");
        exit(2);        /* 失敗したらシェルに戻る */
    }

    SetSeed(  );        /* 乱数のシードを設定 */

      /* MAX_ITEM 個のレコードをファイルに書き込む */
    for (i = 0; i < MAX_ITEM; i++) {
          /* 無意味な文字列を作る */
        for (j = 0; j <  LEN_ITEM_NAME; j++)
            name[j] = 'a' + GetRand(26);          /* 26 はアルファベットの文字数 */
        name[LEN_ITEM_NAME] = '\0';               /* 末尾にヌル文字を追加 */

        prise = GetRand(MAX_PRISE);               /* MAX_PRISE までのint 型の乱数 */

        fprintf(fp, format, i, name, prise);      /* データ書き込み */
    }

    if ((fp = freopen(filename, "r", fp)) == NULL) {  /* 入力モードで開く */
        fprintf(stderr, "ファイルを入力モードで開くのに失敗しました!\n");
        exit(2);                                      /* 失敗したらシェルに戻る */
    }

    printf("レコード番号を入力して下さい ( 0 - %d )?\t", MAX_ITEM - 1);
    while ( scanf("%ld", &n)) {  /* 数字以外の入力でループから抜ける */
        if (n < 0 || n > MAX_ITEM - 1)
            break;                                     /* 不正な値でもループから抜ける */
        fseek(fp, n * REC_SIZE, SEEK_SET);             /* 読み込む位置を決定 */
        fscanf(fp, format, &number, name, &prise);
        printf("No:%2d  Name:%20s  Price:%4d", number, name, prise);
        printf("\nレコード番号を入力して下さい ( 0 - %d )?\t", MAX_ITEM - 1);
    }
    fclose(fp);
}

/* ここまでソースプログラム */

/* while ( ) ループの条件判断の式が、scanf( ) になっています。scanf( ) は変換に成功した変数の数を返すので、数字以外を入力すると 0 を返すので、ループから抜けます。 */

[ユニークなファイル名で開く]←このソース→[空白文字の出現頻度]

青い直線

/* (C) 2000- YFプロ. All Rights Reserved. */    提供:C言語講座−それ自体コンパイルできる教材を使った講座です−

青い直線

サイトマップ / C言語講座出入り口総目次目次:ファイル>ランダムアクセスファイル