3 ファイル処理の方法

3.1 ファイル処理の流れ

先ほどの例でファイル処理の大体の方法を理解したと思う.C言語に限らず,ほとんどの プログラム言語のファイルの処理はどれも似かよっている.それは,図 1のようになっている.人間がデータを記録している 本やノートなどを見る動作と同じようにしている.オープン読み書 きクローズは約束事と理解する必要がある.
図 1: コンピューターのファイル処理と人間の読み書き方法
\includegraphics[keepaspectratio, scale=1.0]{figure/flow_file_manage.eps}

リスト12のプログラムの中で,これらの約束事の記述 の例を図2に示す.人間の動作を考えれば,取 り立ててその流れは難しくない.

図 2: C言語でのファイル処理の例
\includegraphics[keepaspectratio, scale=1.0]{figure/flow_file_manage_ex.eps}

2を見て分かるように,実際のC言語ではオープン読み書きクローズの他に,ファイルポインターの宣言が必要であ る.ファイルポインターについては,次の節で述べることにする.C言語のプログラムで ファイル処理をする場合は,図3に示す手順に従えば良い. ただし,実際のプログラムではエラー処理を書かなくてはならないが,ここでは示してい ない.

図 3: C言語でのファイル処理の流れ
\includegraphics[keepaspectratio, scale=1.0]{figure/flow_file_manage_C.eps}

3.2 ファイルのオープンとクローズ

3.2.1 ファイルポインターの宣言

ファイル処理にはそれに関わる多くの情報が必要である.そのために,ファイルの情報を メモリーの一部に格納する必要がある.その格納場所を示すものがファイルポインターで ある.それは構造体になっており,stdio.hというヘッダーファイルに以下のような 内容が定義(教科書p.377)されている.

このファイルポインター(fp)を使って,全てのファイル関係の処理を行う.なにせ, ファイルに関する情報が全て書かれているので,これを指定すれば,あとはコンピューター が勝手に処理してくれる.面倒くさい処理はコンピューター任せにして,プログラマーは 楽をしようということである.このFILE型の変数(ポインター)を使うためには,次 のように宣言する.

FILE *foo;
これで,FILE型の変数(ポインター)fooを宣言できる.ただし,fooは変数名なので プログラマーが適当な名前をつける.

3.2.2 ファイルのオープン

通常は,fopen()という関数の戻り値をこのポインターに代入する.このファイルを オープンする関数fopen()の書式は,次の通りである.
FILE *fopen(char *filename, char *openmode)
戻り値はFILE型のポインター,ファイル名を表す第一引数はchar型のポインター,オープ ンモードを表す第2引数はchar型のポインターと言うことである.もし,オープンに失敗 すると,NULLという戻り値になる.char型のポインターと難しいことを言っているが, 先のプログラムの例(リスト1, 2)でも分かるように,文 字列をダブルクォーテーションで囲めば良いのである.例えば,hoge.txtというファイル を読み込みモードでオープンする場合
foo=fopen("hoge.txt", "r");

と書く.

オープンモードについては,いろいろ用意されており,教科書のp.382にまとめてある. 細かいファイル処理をする場合は,これらのモードを巧みに使う必要があるが,本講義で は,

とすればよい.バイナリーモードもUNIX(Linux)では関係ないので使わない.

3.2.3 ファイルのクローズ

ファイルをクローズする関数fclose()の書式は,簡単で,次の通りである.
int fclose(FILE *filepointer)
戻り値は,int型で,クローズに成功すると0,失敗するとEOFが返される.引数は,ファ イルポインターのみである.ファイルを開いたら閉じるのが礼儀だと心得て,処理の最後 に
fclose(foo);
と必ず書く.

3.3 ファイルの入出力関数

3.3.1 入出力の方法

いよいよ,ファイルのデータを読み書きするファイル入出力関数について説明する.難し と思うだろうが,実は非常に簡単である.いままで,標準入力(キーボード)と標準出力(ディ スプレイ)に使ってきた関数,printf()scanf()とほとんど同じである. 付録に示すようにキーボードやディスプレイもファイルとして取り扱われるので,同じ手 法がハードディスクにも使える.

まず,入力であるが,一般のファイルと標準入力の場合を並べて書くと

ファイル入力 int fscanf(ファイルポインター,書式指定,引数並び)
標準入力 int scanf(書式指定,引数並び)
となる.ファイルポインターを指定する以外,すべて標準入力の場合と同じである.非常 に単純で簡単である.実際の動作もキーボードからデータを入力するのも,ファイルから 読み込むのも同じイメージで取り扱える.戻り値の整数は入力したデータの個数である. もし,ファイルの最後あるいは読み込みに失敗するとEOFを返す.

出力もまったく同じである.

ファイル出力 int fprintf(ファイルポインター ,書式指定,引数並び)
標準出力 int printf(書式指定,引数並び)
ハードディスクのファイルにデータを書き込むのは,ディスプレイにデータを出力するのと全く同 じイメージである.実際,ファイル出力されたデータを見ると,ディスプレイと同じであ ることが分かる.戻り値の整数は出力した文字数である.書き込みに失敗すると負の値を返す.

これまでから,コンソール入出力とファイル入出力は同じ取り扱いができることが理解で きたであろう.

3.4 ファイル出力の実際

計算結果などを大量のデータはハードディスクに保存しなくてはならない.ファイル出力のコツは, である.

リスト3に三角関数の値をファイル出力するプログラムを示す.

   1 #include <stdio.h>
   2 #include <math.h>
   3 
   4 int main(void){
   5   FILE *out_file;
   6   double x, y1, y2, y3;
   7   double dphi;
   8   int i, n;
   9   
  10   n = 360;
  11   
  12   dphi = 2*M_PI/n;
  13   
  14   out_file = fopen("trifunc.txt","w");
  15   
  16   for(i=0; i<=n; i++){
  17     x=i*dphi-M_PI;
  18     y1 = sin(x);
  19     y2 = cos(x);
  20     y3 = tan(x);	  
  21     fprintf(out_file, "%e\t%e\t%e\t%e\n", x, y1, y2, y3);
  22   }
  23   
  24   fclose(out_file);
  25 
  26   return 0;
  27 }

3.5 ファイル入力の実際

コンピューターを使ったデータ処理では,対象となる大量のデータをハードディスクから読 み込むことが多い.ここでの講義でも,データを読み込むことがある.また,卒研ではな おさらである.数値計算や実験でのファイルからのデータ入力のコツは, である.

リスト4に先ほど作成したファイル内容を読み込み,ディスプレイに出 力するプログラムを示す.

   1 #include <stdio.h>
   2 
   3 int main(void){
   4   FILE *in_file;
   5   double x[500], y1[500], y2[500], y3[500];
   6   int i, j;
   7   
   8   in_file = fopen("trifunc.txt","r");
   9   
  10   for(i=0; i<=499; i++){
  11     if(
  12        EOF == fscanf(in_file, "%lf%lf%lf%lf",&x[i], &y1[i], &y2[i], &y3[i])
  13        ) break;
  14   }
  15   
  16   fclose(in_file);
  17 
  18   for(j=0; j<i; j++){
  19     printf("%f\t%f\t%f\t%f\n",x[j], y1[j], y2[j], y3[j]);
  20   }
  21 
  22   return 0;
  23 }

ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
平成18年6月27日


no counter