これまでプログラムで扱ってきたデータは変数や配列、構造体などの中に格納され使われてきました。
変数や配列はメインメモリ上に配置され、プログラムの終了とともに使えなくなってしまいます。
ゲームを題材にすると分かりやすいと思いますが、多くのゲームにはセーブやロードといったメニューがあります。
そこで使われるのが「ファイル」になります。
セーブは「ファイル」にゲーム内で使われている変数や配列などの情報を格納し、保管しておくものです。
ロードは「ファイル」に保管されたデータを読み込み、再び変数や配列などに格納することです。
この「ファイル」の扱いについて今回から説明します。
ファイル操作の基本的な流れは↓の通りです。
1.ファイルを開く 2.開けたかどうかチェックする 3.データを読み書きする 4.ファイルを閉じる |
実際のプログラムを見ながら1つずつ説明していきます。
ファイルを開くにはfopenという命令(関数)が必要です。
fopenを使うにはstdio.hをincludeする必要があります。
※まだ動かさないでください。
<sample program 110-01>
#include <stdio.h> int main(void) { FILE* fp; /* ファイルを開く */ fp = fopen("Test.txt", "w"); return 0; } |
書けたらコンパイルだけしてみましょう。
fopenもscanfやstrcpyなどと同じく「安全でない」という警告が表示されています。
warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. note: 'fopen' の宣言を確認してください
まだ動かしてはいけないというのは、開いたファイルは閉じなければなりませんが、閉じるプログラムを書いてないからです。
まず
FILE* fp; |
とありますが、これはまだ説明していないポインタというものです。
「ファイルポインタ」と言いますが、ファイルを扱うために必要なものと考えてください。
ポインタについては、後々説明をしますので、今のところはこのまま使います。
fopenの説明ですが、関数というものについて少し触れないと説明しづらいので、ちょっとだけ説明します。
これまで使ってきたscanfやprintf、randなどは関数と言います。
Visual Studioのエディタでは(デフォルトで)命令(キーワード)は青い文字になりますが、関数は黒い文字なので見分けがつくかも知れません。
関数には引数(ひきすう)と戻り値というものが存在します。
引数とは、その関数に渡すデータと思ってください。
戻り値は、その関数から戻されるデータと思ってください。
fopen関数では、
"Test.txt" と "w" という文字列が「引数」 fpに代入されているデータが「戻り値」
です。
"Test.txt"は、これから扱おうとしているファイルの名前です。
"w"は、ファイルを開く時のモードで「write(書き込み)」の略です。
この2つのデータを渡すと、fpに「戻り値」が返ってきます。
ファイルを開くことに失敗した時には「NULL」という特殊なデータが戻されます。
成功した場合は「NULL」以外のデータが戻されます。
この戻り値を確認することで、ファイルを開くことに成功したか失敗したかが分かります。
では、開けたかどうかチェックするプログラムを追加しましょう。
※まだ動かさないでください。
<sample program 110-02>
#include <stdio.h> int main(void) { FILE* fp; /* ファイルを開く */ fp = fopen("Test.txt", "w"); /* エラーチェック */ if (fp == NULL) { printf("OPEN ERROR\n"); return 1; } return 0; } |
fpにNULLが入っていたら開けなかったということでエラー処理を行います。
ここでは画面に「OPEN ERROR」と表示した後で、1をreturnして異常終了したことにしています。
returnについても関数の所で説明する命令ですが、今のところは0だと正常終了、1だと異常終了と考えておきます。
順番から行くと次は「データの読み書き」になりますが、先に「ファイルを閉じる」命令(関数)を書きます。
<sample program 110-03>
#include <stdio.h> int main(void) { FILE* fp; /* ファイルを開く */ fp = fopen("Test.txt", "w"); /* エラーチェック */ if (fp == NULL) { printf("OPEN ERROR\n"); return 1; } /* ファイルを閉じる */ fclose(fp); return 0; } |
fclose関数にファイルポインタであるfpを渡すことで、ファイルを閉じることが出来ます。
これで実行しても安全に終了することが出来ますので、実行してみてください。
<実行結果>
続行するには何かキーを押してください・・・
printfなどは使っていませんので、何も表示されないのは当たり前なのですが、ちょっと確認して欲しいことがあります。
皆さんが作られているプロジェクトのフォルダを開いてみてください。
私は「Project01」という名前でプロジェクトを作りました。
↓がフォルダの画像です。
「Test.txt」というファイルが作られているのが分かりますでしょうか?
「Test.txt」を開いてみましょう。
データを書き込むプログラムは作成していないため中身は何もありません。
「Test.txt」は一旦閉じてください。
では、データを書き込むプログラムを追加しましょう。
<sample program 110-04>
#include <stdio.h> int main(void) { FILE* fp; /* ファイルを開く */ fp = fopen("Test.txt", "w"); /* エラーチェック */ if (fp == NULL) { printf("OPEN ERROR\n"); return 1; } /* データを書き込む */ fprintf(fp, "Hello %d\n", 123); /* ファイルを閉じる */ fclose(fp); return 0; } |
fprintf関数は、最初の引数がファイルポインタであることを除いて、printfと同じように使えます。
この場合、
Hello 123 + 改行
というデータをファイルに書き込むように作りました。
とりあえず、実行してみましょう。
<実行結果>
続行するには何かキーを押してください・・・
相変わらずprintfなどは使っていませんので、画面には何も表示されません。
実際にファイル書き込めているかどうか「Test.txt」を開いてみましょう。
成功していれば↑のようにデータが書き込まれているはずです。
簡単な説明ですが、これでデータの書き込みが出来ました。
次回は読み込みについて説明します。
※ここで作った「Test.txt」は次回も使います!