今週は,数値や文字データをプログラムに読み込んだり出力したりする際に必要となる「ファイルの入出力」を行う.
そもそもWindows,UNIXなどの「オペレーティングシステム」では, あるまとまりをもった数値データや文字データ,画像,動画データの集まりを「ファイル」という単位で管理しており,すべてのファイルには識別のために「ファイル名」がつけられている.
計算結果や画像データ,文章など,さまざまな情報は外部記憶装置(ハードディスクやフロッピーディスク,USBメモリ,CD,DVD等のこと)に「ファイル」として記録しておけば,後で読み出したり,別のコンピュータに持っていくことができる.
たとえば,これまで作ってきたプログラムファイルは「C言語ソースファイル」であり,コンパイルされた.exe形式のファイルは「実行ファイル」と呼ばれる. その他,ディジタルカメラで撮影された「画像ファイル」,「動画ファイル」,今閲覧しているこの演習用ホームページも「ファイル」としてWWWサーバー内に保存されている.
コンピュータのディスク上においては,ファイルはメモリと同様,「0」と「1」の並で表されているが,ファイルには,その性質により大きく分けて二種類あり,それぞれ
と呼ばれている.
プログラム内の変数や配列など,何らかの情報を「ファイル」として保存しておく事を「ファイル出力」または「ファイルに書き出す」と言い,逆にファイルに蓄えられている情報をプログラム内の変数や配列に読み込むことを「ファイル入力」または「ファイルから読み込む」と言う.
ファイル入力とファイル出力をあわせて,ファイル入出力と呼び,これら一連の処理をファイル操作と呼ぶ.
プログラム中でファイルを扱うときの基本的な流れは
である.
#include <stdio.h>
void main()
{
char filename[100]; /* ファイル名のための文字列 */
FILE *fp; /* 0:ファイルポインタを宣言 */
printf("作成するファイル名を入力してください : "); /* これは画面への出力 */
scanf("%s", filename); /* これはキーボードからの入力 */
fp = fopen(filename, "w"); /* 1:ファイルを開く(オープン) */
fprintf(fp, "test ¥n"); /* 2:ファイルに文字列を書き出す */
fprintf(fp, "%d ¥n", 10); /* 2:ファイルに整数を書き出す */
fprintf(fp, "%f ¥n", 3.1415); /* 2:ファイルに実数を書き出す */
fclose(fp); /* 3:ファイルを閉じる(クローズ) */
}
ファイル操作を順に見ていきましょう.
ファイルを扱う場合には,必ずファイルポインタを宣言する.
これは,ファイルはディスク上に複数あるため,どのファイルを扱うのか,そのファイルのどの位置を読み書きしているのかを識別・記憶するためである.
書式:FILE *ファイルポインタ変数名;
たとえば,fp
と言う名前のファイルポインタを使いたい場合は,
FILE *fp;
と書く.(FILE
は構造体であり,ここではfp
は FILE
構造体変数を指すポインタという意味になる.)
あるファイルに読み・書きするためには,まず fopen
関数を使って,ファイルをオープンする必要がある.
書式:ファイルポインタ変数名 = fopen ( "ファイル名","モード");
第1引数はファイル名(文字列型),第2引数は「読み取り」と「書き出し」のモード指定(後述)である.
fopen
関数が成功しファイルが開かれると,開いたファイルの先頭位置(ファイルポインタ)が戻り値として fp
に代入される.
何らかの理由でファイルのオープンに失敗すると (ファイルが存在しない,別のプログラムがファイルを開いている,ファイル名間違い等),fopen
関数は NULL
を返す.
このため,実際のプログラムにおいては,通常は以下のように if
文を用いたエラーチェックを行う.
char filename[] = "data.txt"; /* ファイル名 */
fp = fopen(filename, "r"); /* 書き出しモードの場合 */
if (fp == NULL) {
exit(1); /* exit関数は,ここでプログラムを終了させる関数.要 #include<stdlib.h> */
}
/* ここ以降にファイルの読み書きを行う */
ファイルが開けなかった場合は,その続きの読み書き処理ができないので,上の例のようにプログラムの実行を終了させるための exit
関数を使うか,または return
文で関数を終わらせる.
fopen
関数の第2引数のモードについては以下のとおり.文字列型なので,必ず" "で括る必要がある.
モード | 説明 |
"r" | 読み込み専用で開く.(read) |
"w" | 書き込み専用で開く.(write) |
"rw" | 読み取りと書き込み両方で開く.(read and write) |
"a" | 追加書き込みモードで開く.(append) すでにあるファイルの末尾に追加.もしファイルがなければ新規作成する |
ファイル入出力では画面からデータを読み書きするのに用いた,scanf
, printf
関数によく似た,fscanf
, fprintf
関数をそれぞれ用いる.
書式(ファイル読み込み):fscanf(ファイルポインタ, "書式指定子", 引数, ...);
書式(ファイル書き出し):fprintf(ファイルポインタ, "書式指定子", 引数, ...);
使い方は,scanf
, printf
関数と同じである.
違いは第1引数にファイルポインタを渡す点である.(どのファイルに読み書きするかを識別するため)
fprinf
関数の使用法は,画面出力のprintf
とほぼ同じである.例1:ファイルに実数を書き出す例.(注:以下の4例では,FILE* fp;
や,fopen
など必要な処理が省略されている.)
fprintf(fp, "%f ¥n", 3.14159265);
例2:ファイルに文字列を書き出す例.
char[] str = "Meiji University";
fprintf(fp, "%s ¥n", str);
fscanf
関数は,ファイル中の「スペース記号」または「改行記号」を区切りとしてファイルの内容を読み取り,変数に値を代入する.例3:ファイルに書かれた数値 (例えば「1000」など) を,整数型変数に読み込む例.
int i;
fscanf(fp, "%d", &i); /* &を忘れないこと.アドレスを取り出す演算子 */
例4:ファイルに書かれた文字列 (例えば「Ikuta」など) を,文字列型変数に読み込む例.
char mojiretsu[100];
fscanf(fp, "%s", mojiretsu); /* & は不要! */
ファイルの利用が終わったら,プログラムを終了する前に必ずファイルをクローズする.
書式:fclose(ファイルポインタ);
例:fclose(fp);
これを忘れると,ファイルの書き出しが完了しない場合がある.
以下に,ファイル入出力と,キーボード・画面入出力の比較を示す.
画面出力 | ファイル出力 |
|
|
キーボード入力 | ファイル入力 |
|
|
(1)scanfを使ってキーボードから入力した数値をファイルに保存するプログラムを作成せよ.
(2)上問で作ったファイルに保存された数値を読み込み,画面に表示するプログラムを作成せよ.
(3)角度を0度から360度まで1度ずつ変えたときの,sinの値を各行に出力するプログラムを作成せよ.計算上,円周率はpi=3.141とする.
ファイル名は,"sin.csv"としよう.ファイル名の末尾に .csv (拡張子と呼ぶ)をつけると,Excelで簡単に開くことができる.
sin()
などの算術関数を使う際には #include<math.h>
を書くこと.
結果の例:
0.000000
0.017452
0.034898
....
(4)(3)を利用して,角度を0度から360度まで1度ずつ変えたときの,sinの値,cosの値,tanの値を各列に出力するプログラムを作成せよ.
授業終了時までに完成したプログラムをoh-meijiシステムを使って提出すること.
(提出期限を厳守し,提出用の回に提出しないと採点を行わない)