1月 18日


第13章

ストリーム
教科書 p.290
ファイル(キーボード・ディスプレイも含む)に体する入出力は、 プログラムからはストリーム(stream)を使って行なう。 ストリームとはディスクあるいは他の周辺機器(ディスプレイ・キーボードなど)と 結び付いているデータの送出元および送出先である。
標準ストリーム
教科書 p.291
C言語では、つぎの3つの標準ストリームがあらかじめ準備されている。
入出力のリダイレクト(復習)
教科書 p.205
  コマンド名 < 入力ファイル名↵
とすると、キーボードの代わりに入力ファイルからデータが読み込まれ、
  コマンド名 > 出力ファイル名↵
とすると、ディスプレイの代わりに出力ファイルにデータが書き込まれる。
  コマンド名 >> 出力ファイル名↵
とすると、出力ファイルにデータが追加される形で書き込まれる。
これはC言語ではなく OS(WindowsやUnixなど)の機能で、 リダイレクトと呼ばれる。
FILE
教科書 p.291
FILE型はストリームを操作するために必要な情報を表す型(通常は構造体)。 stdin, stdout, stderr は、このFILEへのポインタ型(FILE *)である。 ファイル・ポインタとは、このFILEへのポインタのことである。 C言語ではファイル・ポインタはストリームと同じような意味で使われる。
ファイルのオープン
教科書 p.292
標準入出力以外のファイルを読み書きするためには、 まず準備(オープン)する必要がある。ファイルをオープンするために fopen関数
    FILE *fopen(const char *filename, const char *mode);
を使う。
ファイルのクローズ
教科書 p.294
ファイルを使い終わったらクローズする必要がある。 fclose関数
    int fclose(FILE *stream);
を使う (List 13-1)。
ファイルからの読み出し
教科書 p.296
ファイルからデータを読みとるには fscanf関数
    int fscanf(FILE *stream, const char *format, ...);
を使う (List 13-2, テストデータ) 。第1引数にファイル・ポインタが増えている以外は使い方はscanf関数と同じ。
ファイルへの書き込み
教科書 p.298
ファイルに出力するためには、fprintf関数
    int fprintf(FILE *stream, const char *format, ...);
を使う (List 13-3, List 13-4) 。 第1引数にファイル・ポインタが増えている以外は使い方はfprintf関数と同じ。
fgetc関数
教科書 p.302
    int fgetc(FILE *stream);
ストリームから一文字読み込む (List 13-6, cf. List 13-5) 。 ファイル・ポインタの引数を取る以外は使い方はgetchar関数と同じ。
fputc関数
教科書 p.304
    int fputc(int c, FILE *stream);
ストリームに一文字書き込む(List 13-7)。 第2引数のファイル・ポインタが増えている以外は使い方はputchar関数と同じ。
テキストとバイナリ
教科書 p.306
数値データを正確に保存したい、あるいは、少ない容量で保存したい場合には バイナリファイルに保存する (List 13-9, cf. List 13-8, List 13-10)。 バイナリモードで書き込み・読み出しをするにはつぎの関数を使う。
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
(これらの関数を使用する時は、ファイルをオープンする時もバイナリモードを指定しなければならない。)
乱数
教科書には載っていない

疑似乱数(でたらめに見える数)を発生させるには randという関数を用いる。

  int rand(void);  /* stdlib.hが必要 */

randは 0から、 ある非常に大きな数(RAND_MAXというマクロの値、 bcc32の場合、約 20億)の間の整数を返す。

このため、0〜1の範囲の乱数が必要な場合は (double)rand()/RAND_MAX、 0から 5の整数の乱数が必要なときは rand()%6のような式を用いる。 (後者はRAND_MAXが充分大きくないと、 無視できない偏りが生じるおそれがある。)

srand関数は疑似乱数の“種”をセットする。

  void srand(unsigned int seed);  /* stdlib.hが必要 */

randは乱数といっても、人間にとってでたらめに見えるだけで、 実際には、ある計算規則に基づいて数を計算している。
rand, seedの実装例(K&Rより)
#define RAND_MAX 32767 unsigned long int next = 1; int rand(void) { next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % (RAND_MAX+1); } void srand(unsinged int seed) { next = seed; } このため、srandを実行しなければ、 randはプログラムの実行のたびに同じ乱数系列を発生する。

例えば、プログラム中でrandを使うまえに、現在時刻を種にして

  srand((unsigned)time(NULL));    /* time.hが必要 */

という文を実行する。

例: saikoro.c — 5個のさいころを振った時の和がいくつになりやすいか、 をシミュレーションするプログラム


戻る


Koji Kagawa(kagawa@eng.〜)