第二十八話 ファイルへの読み書き
立花先輩はカタカタとキーボードを打って、コードを書いていった。
「よし、出来た。イツキくん、見てみて」
「どれどれ……」
俺は画面を覗き込む。
/* ファイルをオープンしてセーブ savefile.c */
#include<stdio.h>
#include<stdlib.h> /* exit関数用 */
int main(void)
{
FILE *fp;
fp = fopen("test2.txt","w"); /* wモード(write、書き込み)でファイルを開く */
if (fp == NULL) { /* エラーチェックも忘れないでよ */
printf("ファイル開けるのに失敗!\n");
exit(1); /* プログラム強制終了 */
}
fputs("テストなの\n", fp); /* 書き込み */
fclose(fp); /* 開けたファイルストリームは最後に必ず閉めること! */
return 0;
}
「ま、コメントを書いておいたから、大体の流れは解ると思うけど」
「ええ、まあ。でも、FILEって型は初めて見ます」
「あ、これは型っていうより、構造体だから」
「構造体?」
俺と西原さんは怪訝な顔をする。
「うーん、この説明は次回に後回しね。とりあえず、今は型って思ってもいいけど。使う分にはそう思ってても問題ないし。で、このfpって変数が、ファイルとのストリームに使うわけ」
「結構、簡単に作れるんですね」と西原さん。
「まず、fopen関数でファイルストリームを開いて、そのポインタをfp変数に返すわけね。第一引数がファイル名で、第に引数が開くときのモード、書き込みしたい時は『w』で、読み込みたい時は『r』ね。で、ファイルに追加書き込みしたいなら、『a』」
「わかりやすいな。じゃ、次のNULLって?」
「それは、ヌルポインタっていって、fopen関数が失敗したら返すって決まっているの。だったら開けるのに失敗したって事だから、そのままプログラムも終了させるわ」
俺は大体のプログラムが理解できた。
「じゃあ、書き込みは、このfputs関数で、最後にcloseで閉めるわけか」
「その通りね。ちなみに一文字だけ書き込みたいなら、fputc関数よ。関数名putの最後がcだとchar、つまり一文字で、最後がsだとstring、文字列になるわけ」
俺は頷く。
「じゃ、イツキくんもわかったところで、実行してみよう」
先輩は、プログラムを実行させた。もちろん、画面には何の変化も無かったが、dirコマンドをするとtest2.txtが作られている。メモ帳で開いてみると、もちろん「テストなの」が書き込まれていた。
「ま、書き込みはこれでOKよね。じゃ、次はファイルの読み込みについて」
先輩は プログラムを少し改造していった。
/* ファイルをオープンしてロード loadfile.c */
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
FILE *fp;
char buf[256];
fp = fopen("test2.txt","r"); /* rモード(read、読み込み)でファイルを開く */
if (fp == NULL) { /* エラーチェックも忘れないでよ */
printf(“ファイル開けるのに失敗!¥n“);
exit(1); /* プログラム強制終了 */
}
fgets(buf,256, fp); /* buf配列に読み込み */
printf(buf); /* 読み込んだのを表示させる */
fclose(fp); /* 開けたファイルストリームは最後に必ず閉める! */
return 0;
}
「ほとんど変わりませんねー」と西原さん。
「ま、fopenを読み込みモードにしたのと、fputsの代わりにfgetsを使ったくらいね。fgetsは一行ずつ読み込む関数で、第一引数に読み込む先の文字配列の変数を、第二引数には読み込み最大数を、第三引数は使うファイルストリームを書くのよ」
先輩はプログラムを実行させる。すると画面に、「テストなの」が表示される。
俺は頷いた。
「これで、ファイル操作もバッチリですよ。さっそくハイスコア ルーチンを作ってみます」
「そうね。でも、そろそろメイン関数に全部詰め込むと、関数が長くなってきたから、書き込みと読み込みは別の関数に分けた方がいいわよ。メイン関数は短い方が、プログラム全体の流れが読みやすくなるわ」
「はい」
俺は答えるとプログラムを作っていった。