◆◆◆◆アマゾンで購入する◆◆◆

14.ファイルの入出力 
           内    容
(1)ファイルの入出力の準備
(2)オープンとクローズ
(3)代表的な入出力関数
(4)ファイル出力の例
(5)ファイル入力の例
(6)出力の際の常套手段
(7)演習


(1)ファイルの入出力の準備

キーボード入力やディスプレイ表示は,
標準入出力と呼ばれ,
黙っていても使えるものとして扱われています。

いわば,人間で言えば,
目や口のように生まれながらにして
備わっている入出力装置だと扱われています。

一方,ディスクファイルは,
メモ用紙やノートの類と考えればよいでしょう。

必要であれば,これらを手に入れ,
どのメモ用紙か,どのノートのどこに書くかを
指定しなければなりません。

すなわち,ディスクファイルを使うには,

■どのデバイスの,どのフォルダの,
  どのファイルを使うか?を指定。

■ 書き込むのか,読み込むのか?を指定。
  これをモードといいます。

■ ノートに書き込んだり,ノートを読むには,
  最初に,ノートを取り出して
  開かなければならないように,
  Open(開く)という操作が必要。

■ ノートに書き込んだり,
  ノートを読む必要がなくなったら,
  ノートを閉じてしまうように,
  Close(閉じる)という操作が必要。

(2)オープンとクローズ

まず,
入出力用のバッファや制御用の構造体への
ポインタを示す変数を宣言します。

    FILE *fstream;

この構造体をストリームといいます。

ファイルを開くには,次のように書きます。

   fstream = fopen(ファイル名,モード);

ファイルを閉じるには,ストリーム変数を使って

   fclose(fstrem);

と指定します。

ファイル名は,

   ドライブ名:\フォルダ名\サブフォルダ名¥…\ファイル名.拡張子

のようにフル名で指定します。

モードは,次の記号で指定します。

記号 意味
"r" : 読込み専用
"w" : 書込み専用
"a" : 追加用
"r+": 既存ファイルを更新用として
"w+": 新規ファイルを更新用として
"a+": ファイルの終りから更新用として
"rt": テキストファイルを読込み専用として
"wt": テキストファイルを書込み専用として


なお,更新用とは,
読込みと書込みを同時に行うような入出力です。

プログラムの誤りによって
ファイルを壊すことも多いので,
特殊なプログラム以外では,
あえて避けたほうがよいでしょう。

更新型の典型であるメモリのほうが高速ですので,
私としては,メモリ内で更新して,
結果を別ファイルに出力するほうを推奨します。

(3)代表的な入出力関数

入出力操作を行う代表的な関数を以下に示します。

int fgetc(FILE *stream)
 ストリームから読み込んだ1文字を int に変換して返却。 ファイルエンドやエラーのときEOFを返却。
int fputc(int ch, FILE *stream)
 ストリームに1文字を出力。エラーのときEOFを返却。
fclose(FILE *stream)
 ファイルをクローズ。


(4)ファイル出力の例

キー入力された文字列を
ファイルに出力する例を示します。

[プログラム例]
#include "stdafx.h"
int main(int argc, char* argv[])
{
 FILE *fout; char fname[80]; int ch;
 printf("出力ファイル名:");
 scanf("%s",fname);
 /* scanf最後の[CR]が読み込れて */
 /* しまうので,ダミー読込み    */

 ch=getchar();
 if((fout=fopen(fname,"wt"))!=NULL)
 {
  ch=getchar();
  while(ch !=EOF)
  {
    if(fputc(ch,fout)==EOF) ch=EOF;
    else ch=getchar();
  }
  fclose(fout);
 }
}

(5)ファイル入力の例

テキストファイルから読込み,
ディスプレイに表示する例を示します。

[プログラム例]
#include "stdafx.h"
int main(int argc, char* argv[])
{
 FILE *finp;char fname[80];int ch;
 printf("入力ファイル名:");
 scanf("%s",fname);
 if((finp=fopen(fname,"rt"))!= NULL)
 {
  while((ch=fgetc(finp)) != EOF) printf("%c",ch);
  fclose(finp);
 }
}

(6)出力の際の常套手段

ファイル名を間違って指定したために,
大事なファイルを壊してしまった経験は,
だれでもありますね。

このようなトラブルを最低限にするために,
以下のようにするのが通常です。

@ ファイルが既に存在していたら,上書きするかどうかを問い合わせる。
A それでも間違う可能性があるので,既に存在しているファイルの拡張子を変えて残し,新規ファイルとして出力する。

以上のようにすることで,
間違えて上書きしてしまっても
復旧できるようになります。

ここで使うのは,関数は,以下のとおりです。

ファイル削除 remove(ファイル名)
ファイル名変更 rename(旧ファイル名,新ファイル名)


[プログラム例]
#include "stdafx.h"
#include <conio.h> /* エコー表示なしで入力するために */
static FILE *fout;

void fname_change(char name[])
{
 int i,ip;char new_name[81];
 for(i=0;(i<76) && (name[i] !=0);i++) new_name[i]=name[i];
 ip=i--;
 /* 拡張子の位置を見つける*/
 while((i>=0) && name[i] !='.')i--;
 if(i>0)ip=i;
 new_name[ip]='.';
 new_name[ip+1]=new_name[ip+2]=new_name[ip+3]='$';
 new_name[ip+4]=0;
 remove(new_name); /* .$$$のファイルを削除 */
 rename(name,new_name); /* .$$$にファイル名を変更 */
}

/* 読込みモードでOpenし, */
/* ファイルがあるとみなす */
int ex_open(char name[])
{
 char ch;
 if((fout=fopen(name,"r")) !=NULL)
 {
  fclose(fout);
  printf("\n 同一のファイル名があります。");
  printf("上書きしますか(Y/N)?");
  ch = _getch(); /* エコー表示なしの1文字入力 */
  while(ch!='y' && ch!='Y' &&ch!='n' &&ch!='N') ch=_getch();
  if(ch=='n' || ch=='N') return 1;
  fname_change(name);
 }
 if((fout=fopen(name,"wt"))==NULL) return 2;
 return 0;
}

int main(int argc, char* argv[])
{
 char fname[80];
 printf("ファイル名:"); scanf("%s",fname);
 if(ex_open(fname)==0)
 { /* この部分にファイル出力処理を記述する */
  fprintf(fout,“\n Test Dayo”); /* テスト用 */
  fclose(fout);
 }
}

(7)演習

テキストファイルをコピーするプログラムを作成して下さい。
なお,出力するファイルの同一ファイルがあったら,
上書きするかどうかを確認するようにしてください。

 1.C言語の誕生

 2.C言語の仲間たち

 3.新しい言語をすばやく覚えるには

 4.Cでプログラミング

 5.データの入れ物 変数の考え方

 6.注釈・定数

 7.プログラムの実行順序

 8.配列

 9.C言語特有の代入文・制御構造

10.関数の話

11.構造体と共用体

12.ビット演算

13.プログラムの場所をポインタで

14.ファイルの入出力

15.色々な便利な方法