(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.色々な便利な方法
|