fgetc関数を使ってテキストファイルから1バイトずつ情報を読み取る処理について解説します。
fgetc関数は、fgets関数やfscanf関数などと比べると、読み取る効率の悪い関数ですが、一番シンプルな使い方ができます。
【基本】fgetcで1文字読み取るサンプル
fgetc関数を使いテキスト形式のファイルから半角1文字を読み取り表示してみます。
この記事内のプログラムで読み取るテキストファイルは、全て以下の fruits.txt を利用します。
fruits.txt ※プログラムと同じフォルダに事前に作成してください
Apple Tomato Banana Lemon Grape
サンプルプログラム: file_fgetc.c
/* ファイルから1文字読み取って表示する */
#include <stdio.h>
#include <stdlib.h> /* exitを呼び出すために必要 */
int main(void)
{
FILE *fp;
int c;
/* ファイルを開く */
fp = fopen("fruits.txt", "r"); /* ← 存在するファイル名を指定して下さい */
if(fp == NULL){
printf("ファイルが開けません\n");
exit(1);
}
/* ファイルから1文字読み込む */
c = fgetc(fp);
printf("[%c]\n", c);
/* ファイルを閉じる */
fclose(fp);
return 0;
}
実行結果
[A]
ファイルから1バイトずつ読み取る手順としては、
1.fopen関数で対象のファイルを読み取りモード(r)を指定して開く
2.fgetc関数で1バイトずつ読み取る
3.fclose関数でファイルを閉じる
となります。
それぞれポイントを解説します。
fopen関数で読み取りモードで開く
fp = fopen("fruits.txt", "r");
if(fp == NULL){
printf("ファイルが開けません\n");
exit(1);
}
fopen関数は第1引数に開きたいファイル名、第2引数にファイルオープンモードを指定します。ファイルオープンモードに読み取り専用として開く場合は、 “r” を指定します。ファイルオープンモードについては以下を参照してください。
fopen関数の戻り値を受け取っている変数fpはFILE構造体またはファイルポインタと呼ばれる変数です。ファイル処理を扱うプログラムには必ず宣言が必要です。ファイルポインタのイメージとしてはファイルの場所を指し示すもの、と考えてください。(変数名の先頭に*がつきますが、ポインタ変数とは全く別物と考えてください)
ファイル構造体宣言(*の後の fp は変数名だが、一般にfpを使うことが多いです)
FILE *fp;
fopen関数は、指定したファイルを正常に開くと対象ファイルへのファイルポインタを返します。ただし、ファイルが見つからなかったり何らかの理由で開けなかった場合、NULLを返します
NULLはヘッダファイルstdio.hで定義されている定数です。主にファイル処理のエラー時の戻り値やポインタ変数で何も示さない場合などに利用されます。
fgetc関数で1バイトずつ読み取る
ファイルを正常に開いた場合、fpには対象ファイルへのファイルポインタが返ってきます。
これをfgetc関数の引数に使って対象ファイルから1バイト(半角1文字)読み取ることが出来ます。
fgetc関数の戻り値は、int型の整数として返されます。
c = fgetc(fp);
fruits.txtの先頭行は Apple となっています。最初の文字である A が返されるわけですが、実際にはint型の戻り値のため、文字 A のASCIIコード番号である 65 が返されることになります。
サンプルプログラムではこれをprintf関数の書式指定子を使い文字表示させています。
printf("[%c]\n", c);
fclose関数でファイルを閉じる
fopen関数で開いたファイルは必ずfclose関数を使って閉じる必要があります。(読みかけの本を開いたままにしてはダメだよ!という事ですね)
fclose関数の引数には、ファイルポインタを指定します。
fclose(fp);
以上がファイルから1バイトずつ読み取る手順となります。
ファイルポインタに関してのイメージ図
ここまでイメージ出来たでしょうか???
もう一つ大事な点があります。ファイルポインタに関してです。
fgetc関数を1度実行すると、ファイルポインタ(上記プログラムでは変数 fp )はインクリメントされます。ですからfgetcを繰り返していくと開いたファイルを先頭から末尾まで順に読み取ることができるのです。
知らなくてもいい話ですが、知っておいて損はないと思うので、イメージ図にしてみました。
fopen関数を使ってファイルを開いたときのイメージ
fopen関数を使ってファイルを開くと、ファイルポインタの位置はファイルの先頭になります。
fgetc関数などを使って、ファイルから読み取りを行うとファイルポインタの値が変化します。
次をご覧ください。
fgetcを実行したときのファイルポインタのイメージ
fgetcを実行してファイルから半角1文字読み取りを行うとファイルポインタはインクリメント(1つ増加)され次の文字を指し示します。
fgetc関数を実行する毎にファイルポインタが次の位置を指し示すため、次のように複数回繰り返すと先頭から順に半角1文字ずつ読み取ることができます。
例)fgetc関数を3回繰り返す ファイル名: file_fgetc_3x.c
/* fgetc関数を3回繰り返す */
#include <stdio.h>
#include <stdlib.h> /* exitを呼び出すために必要 */
int main(void)
{
FILE *fp;
int c;
/* ファイルを開く */
fp = fopen("fruits.txt", "r");
if(fp == NULL){
printf("ファイルが開けません\n");
exit(1);
}
/* ファイルから1文字ずつ読み込む */
c = fgetc(fp);
printf("[%c]\n", c);
c = fgetc(fp);
printf("[%c]\n", c);
c = fgetc(fp);
printf("[%c]\n", c);
/* ファイルを閉じる */
fclose(fp);
return 0;
}
実行結果
[A] [p] [p]
fgetcを3回実行したので、先頭行 Apple の3文字目までを読み取ることが出来ました。
ファイルポインタ(=ファイル構造体)については以下も参考になさってください。
以上のように、ファイルポインタのインクリメントを利用すると、fgetc関数を使ってファイルの終わりまで1文字ずつ読み取って全て表示するプログラムを作成することが出来ます。
次をご覧ください。
【応用】ファイル内容を全て表示するサンプル
コンピュータでは、ファイルの終わりをEOF(=End Of File)という情報で表現します。
fgetc関数は、ファイルの終わりを読み取るとEOFを返すことになっています。これを利用してファイルの先頭からEOFの手前までを読み取って表示するプログラムを示します。
file_fgetc_eof.c
/* ファイルの終わりまで1文字ずつ読み取って表示する */
#include <stdio.h>
#include <stdlib.h> /* exitを呼び出すために必要 */
int main(void)
{
FILE *fp;
int c;
/* ファイルを開く */
fp = fopen("fruits.txt", "r");
if(fp == NULL){
printf("ファイルが開けません\n");
exit(1);
}
/* ファイルをEOFまで読み取る */
while((c = fgetc(fp)) != EOF){
printf("%c", c);
}
/* ファイルを閉じる */
fclose(fp);
return 0;
}
実行結果
Apple
Tomato
Banana
Lemon
Grape
fgetcは、ファイルの終端を読み取るとEOFを返すため、繰り返し処理の条件としては、fgetc関数でEOFが読み込まれない時は繰り返す、となります。
上記プログラムのファイル読み取り部分だけを分かりやすく記述するとこんな感じかと思います。
/* ファイルをEOFまで読み取る */
c = fgetc(fp);
while(c != EOF){
printf("%c", c);
c = fgetc(fp);
}
ただし、この記述はループ処理の内と外に c = fgetc(fp); の処理が2回登場して少し冗長な感じがします。通常は、while文の記述を改良して
while((c = fgetc(fp)) != EOF){
:
}
のようにします。
これはfgetc関数を使ってファイルの終わりまで読み取る定番の記述です。
ここまで長々と説明してしまいましたがファイル処理の何たるかが理解して頂ければ幸いです。
以上、fgetc関数を使ってテキストファイルから1バイトずつ情報を読み取る処理についてでした。
本は読み終えたら閉じる。ファイルは開いたら閉じよう!
コメント