ファイルポインタ変数fpを引数に用いるfgetc関数を考察してファイルポインタ変数の本質を垣間見てみましょう

fgetc関数を使ってハードディスク内のファイルに保存された文字列から1文字だけ文字を読み取ってみましょう

🌻  🌻


fgetc関数を使ってハードディスク内に保存されているファイルの


データを


読み取ってみる?


🌻🌻



ソーラー「

fgetc(エフゲットシー)


なんだかかっこいい名前の関数だね。



🌻🌻

fgetc(エフゲットシー)関数とは


ハードディスク内のファイルに保存された半角英数字の文字列の


左端の文字から1文字ずつ


その文字のアスキーコードを


読み取る関数なんだよ


とりあえず


実際に使っているところを見れば


よくわかると思うな


そのためには


まず


ハードディスク内のTEN-GOGO-C-languageファイルに


何か半角英数字の文字列が保存されてないとね💖



次のプログラムを使って

ハードディスク内のTEN-GOGO-C-languageファイルに半角英数字の文字列データ


Hello!world


を保存してみるよ


🌼      🌼

#pragma warning(disable: 4996)

#include <stdio.h>

int main (void){


FILE *fp;

fp=fopen("TEN-GOGO-C-language.txt","w");

if(fp==NULL){

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


fputs("Hello!world\n",fp);


fclose(fp);

return 0;

}


コンパイル結果


Hello!ファイルオープンに成功しましたよ~ん


ソーラー「これで


TEN-GOGO-C-language.txtファイルに


Hello!worldが保存されたわけだね。」



🌻🌻

さあて

さて

fgetc関数を使って

ハードディスク内のファイルに保存された半角英数字の文字列データ


Hello!worldの


左端の文字Hのアスキーコードだけを


読み取り


コマンドプロンプト画面に表示してみるよ


🌼🌼


#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE *fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int c;

c = fgetc(fp);


printf("%c", c);


fclose(fp);

return 0;

}


コンパイル結果

Hello!ファイルオープンに成功しましたよ~ん

H続行するには何かキーをおして下さい・・・_


ソーラー「??


おおっ なんか


Hがprintf出力表示されたね。


なるほど


fgetc(fp);


が実行されると


fgetc(fp)には戻り値として


文字Hに対応するアスキーコード(数値データ72)


が返されることになるんだね




🌻   🌻


そのとき


ハードディスク内の文字列データHello!worldのHのアスキーコード72が


コンピュータのメモリに格納されることになりますが


そのメモリのアドレスは


ファイルポインタ変数fpに格納されているアドレスとなります



🌼   🌼


ソーラー「そ、そうなんだ


そして


c = fgetc(fp);


により


fgetc(fp)の戻り値は


変数宣言


int c;


によって作製された


変数cに格納されることになるんだね。」



🌻🌻


その通り\(^o^)/


🌼🌼


ソーラー「もう1度繰り返すと


c = fgetc(fp);


のfpはファイルポインタ変数です


c = fgetc(fp);


が実行されると


c = fgetc(fp);



fgetc(fp)は


ハードディスク内の文字列データHello!worldのHに対応する


戻り値(数値データ72、アスキーコード72)

を返されることになります


その戻り値(数値データ72、アスキーコード72)は


int c;によって変数宣言されることにより作製された


変数cに格納されることになるんだね。



その戻り値が格納された変数cを


%c出力変換指定子を使ってprintf出力表示すると


コンパイル結果は


H


となるんだね



🌻🌻


ではね


c = fgetc(fp);を2回つかって


ハードディスク内のファイルに保存されている半角英数字の文字列


2文字分の


アスキーコードを取り込んでみるよ


さっきのプログラムの


c = fgetc(fp);

printf("%c", c);

の部分を


c = fgetc(fp);

printf("%c", c);

を2回使って


c = fgetc(fp);

printf("%c", c);


c = fgetc(fp);

printf("%c", c);


に書き換えてみると~


#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE *fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int c;


c = fgetc(fp);

printf("%c", c);


c = fgetc(fp);

printf("%c", c);


fclose(fp);


return 0;

}


ビルド実行結果


Hello!ファイルオープンに成功しましたよ~ん

He続行するには何かキーをおして下さい・・・_



ソーラー「なんだか よくわからないけど


Hello!worldの


2文字He


がコマンドプロンプト画面に表示されたね


どうやら

1回目の

c = fgetc(fp);

printf("%c", c);


が実行されると

H

がコマンドプロンプト画面に表示され


2回目の

c = fgetc(fp);

printf("%c", c);


が実行されると

e

がコマンドプロンプト画面に表示されるみたいだね。


でもプログラムの仕組みがよく分からないね?


なんで


同じ命令文


c = fgetc(fp);

printf("%c", c);


を行っているのに


コマンドプロンプト画面に表示される文字が


H

e

変化してるのかな?


  🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓

 ここに


ファイルポインタ変数fpが


一定のアドレスを格納しながら


そのアドレスのメモリにデータを格納するという特徴が表れています


 🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓🍓



fgetc(fp)


が実行されると


fgetc(fp)の戻り値である


ハードディスクのファイルに保存されている半角文字Hのアスキーコード72が


ファイルポインタ変数fpの格納しているアドレスの


メモリに格納されます


そのメモリに格納されたデータを変数cに


int c;

c = fgetc(fp);

と代入して


printf("%c", c);


を行い


コマンドプロンプト画面にHを表示しています


次に


c = fgetc(fp);


が行われると


文字列Hello!worldの文字eに対応するアスキーコードが


ファイルポインタ変数fpが格納しているアドレスのメモリに格納されます


ファイルポインタ変数fpが格納しているアドレスは変化しないので


文字Hに対応するアスキーコード


の上に


文字eに対応するアスキーコードが


上書きされて格納されることになります


ファイルポインタ変数fpを用いて


データをメモリに格納した場合


同じメモリにデータは格納されるのですね


そして


ファイルポインタ変数fpが格納しているアドレスは変化しないことを


次のプログラムで確認してみます

👇

#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE *fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");

printf("%p\n", fp);

int c;

c = fgetc(fp);

printf("%p\n", fp);


c = fgetc(fp);

printf("%p\n", fp);


printf("%d\n", c);

printf("%c\n", c);


fclose(fp);

return 0;

}


ビルド実行結果


008B5A08

008B5A08

008B5A08

101

e


ソーラー「

FILE *fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");



が実行されると


ファイルポインタ変数fpが格納しているアドレスは


008B5A08


となりますが


c = fgetc(fp);


が実行されても


ファイルポインタ変数fpが格納しているアドレスは


008B5A08


もう1回


c = fgetc(fp);


が実行されても


ファイルポインタ変数fpが格納しているアドレスは


008B5A08


のまま


変化していないね


つまり


文字Hに対応するアスキーコードを格納しているメモリ



文字eに対応するアスキーコードを格納しているメモリ


は同じ


ファイルポインタ変数fpが格納しているアドレス


008B5A08


のメモリになっているというわけです



同じアドレスを格納するファイルポインタ変数fpを用いた


c = fgetc(fp);

printf("%c", c);


が2回おこなわれても


コマンドプロンプト画面に表示される文字は変化していくことになります


🌼 🌼


ソーラー「ファイルポインタ変数fpの特徴が


うまくfgetc関数の中で使われているってわけだね」


🌻🌻


ポインタ変数の仕組みはいろんなところで登場してくるね


それでは 次の


プログラムはどうかな?


#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE *fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int c;

c = fgetc(fp);


printf("%d", c);

printf("%c", c);


fclose(fp);

return 0;

}


コンパイル結果

Hello!ファイルオープンに成功しましたよ~ん

72H続行するには何かキーをおして下さい・・・_


はい


72Hが表示できました


🌼🌼


ソーラー「72H???


この72Hというコンパイル結果と


プログラム内の


int c;

c = fgetc(fp);


printf("%d", c);

printf("%c", c);


の意味が?


よくわからないね。



🌻🌻🌻


そうだね


確かに


ソーラーさんはどう思う?



🌼  🌼



ソーラー「c = fgetc(fp);


は 

fgetc(fp)関数に返された戻り値(アスキーコード72)を


変数cに格納しているんだよね」



🌻🌻


その通り\(^o^)/その通り\(^o^)/


🌼🌼


ソーラー「そして


その戻り値が格納された変数cを


%d出力変換指定子を使って


printf("%d", c);



printf出力表示すると



コンパイル結果は


72


%c出力変換指定子を使って


printf("%c", c);


printf出力表示すると


コンパイル結果は


H


となっている・・・


ははあ、わかった


fgetc(fp)


の戻り値は


ファイルポインタ変数fp


に格納されたアドレスのメモリに格納された


Hのアスキーコード72


72となっている


つまり


fgetc(fp);

を実行すると


ハードデイスクのファイル内に保存されている半角英数字のアスキーコードが戻り値として


fgetc(fp)に返されるというわけなんだね。


そして 今のプログラムの場合


アスキーコード72は


変数宣言int c;


により作成された変数cに格納されたというわけなんだ。


だから

命令文


%d出力変換指定子が用いられた

printf("%d", c);

が実行されると72が表示され



%c出力変換指定子が用いられた

printf("%c", c);

が実行されると


変数cが格納している

72

つまり

アスキーコード72

に対応するHが


コマンドプロンプト画面に


表示されるわけなんだね。


%c出力変換指定子は


1から127までのアスキーコードを


それに対応する半角英数字に変換することができるからね」


🌻  🌻


それでは 次の


プログラムはどうかな?


#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE *fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int c;

c = fgetc(fp);

printf("%c", c);


    c = fgetc(fp);

printf("%c", c);


    c = fgetc(fp);

printf("%c", c);


    c = fgetc(fp);

printf("%c", c);


    c = fgetc(fp);

printf("%c", c);


fclose(fp);

return 0;

}


コンパイル結果

Hello!ファイルオープンに成功しましたよ~ん

Hello続行するには何かキーをおして下さい・・・_


🌼


ソーラー「わかった


つまり


c = fgetc(fp);

を使って


変数cに半角英数字Hのアスキーコードを読み込むと


次に


c = fgetc(fp);

を使って

変数cに格納されるアスキーコードは

Hではなく

その隣の文字

e

のアスキーコードとなり


さらに

c = fgetc(fp);

を使って

変数cに格納されるアスキーコードは

eではなく

その隣の文字

l

のアスキーコードとなるんだね」



🌻🌻


そう、そして


fgetc関数は半角英数字のアスキーコードしか読み取ることができないわけではないんだよ


ひらがな(2バイト文字)などの文字コードを読み取ることもできます


ひらがなの画像データには


数値データが割り振られており


その数値データを用いて


ひらがなの画像データをコマンドプロンプト画面に表示したりできるんだよ


その数値データが2バイトのメモリにわたって格納されているから


ひらがなは2バイト文字と呼ばれるんだ


だけど


ちょっと注意点があるんだ


ひらがなで構成された文字列ハローワールドを


次のプログラムを使って


TEN-GOGO-C-languageファイルに保存し



#pragma warning(disable: 4996)

#include <stdio.h>

int main (void){


FILE *fp;

fp=fopen("TEN-GOGO-C-language.txt","w");

if(fp==NULL){

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


fputs("ハローワールド\n",fp);


fclose(fp);

return 0;

}


ハードディスク内の


ファイルに保存された


文字列データ ハローワールドのハの文字コードを


fgetc関数を使って


よみこんでから


printf("%c", c);


を実行して




コマンドプロンプト画面に表示しようとしても


👇


#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE *fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int c;

c = fgetc(fp);


printf("%c", c);


fclose(fp);

return 0;

}


ビルド実行結果


Hello!ファイルオープンに成功しましたよ~ん


👆


・が表示されるのみで



は表示されないのです




🌼  🌼


それは


fgetc関数は半角英数字のアスキーコードしか読み取ることができない


つまり


半角英数字などの1バイト文字のアスキーコードしか読み込むことができないからなのかしら?



🌻  🌻



ソーラー「そうなんだ



fgetc関数は


半角英数字などの1バイト文字のアスキーコードしか読み込むことができないので


ハのような2バイト文字の文字コードを読み取ることができないんだ


だけど


fgetc関数を


                2回用いれば



ハのような2バイト文字の文字コードを読み取ることができるんだよ


そのプログラムはこちらです

👇

#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE* fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int c;


c = fgetc(fp);

printf("%c", c);


c = fgetc(fp);

printf("%c", c);


fclose(fp);

return 0;

}


プログラムの実行結果


Hello!ファイルオープンに成功しましたよ~ん

C:\Users\solar\source\repos\Project2\Debug\Project2.exe (プロセス 29952) は、コード 0 で終了しました。

このウィンドウを閉じるには、任意のキーを押してください...


🌼  🌼


わわっ



が表示された!


c = fgetc(fp);

printf("%c", c);


c = fgetc(fp);

printf("%c", c);


が実行されると


printf("%c", c);



2回実行されているのに


1文字だけ



が表示されているのね



🌻  🌻




ソーラー「そう


ここは fgetc関数の


特徴だね



c = fgetc(fp);

printf("%c", c);


c = fgetc(fp);

printf("%c", c);


が実行されると


c = fgetc(fp);



2回実行されているので


2バイト文字である


ハの文字コードを


読みとったことになるんだね


c = fgetc(fp);



1回実行すると


2バイト文字である


ハの文字コードの半分の1バイト分のデータを読み取り



c = fgetc(fp);


もう

1回実行すると


ハの文字コードの残り半分の1バイト分のデータを読み取るんだ


結局


合わせて


2バイト文字である


ハの文字コード


を読み取ったことになるんだね


そして



をコマンドプロンプト画面に表示するには



c = fgetc(fp);


を実行するごとに


printf("%c", c);


を実行しないといけないんだ


printf("%c", c);



2回実行しないと



をコマンドプロンプト画面に表示することはできないんだよ


だから


1回目の


c = fgetc(fp);


を実行した後


printf("%c", c);


を実行せず


2回目の

c = fgetc(fp);


を実行して


printf("%c", c);


を実行した場合


以下のプログラムのように

👇


#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE* fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int c;


c = fgetc(fp);

//🌞printf("%c", c);を実行していません


c = fgetc(fp);

printf("%c", c);


fclose(fp);

return 0;

}


プログラムの実行結果


Hello!ファイルオープンに成功しましたよ~ん

n

C:\Users\solar\source\repos\Project2\Debug\Project2.exe (プロセス 18688) は、コード 0 で終了しました。

このウィンドウを閉じるには、任意のキーを押してください...


👆

ハが表示されず


n

が表示されることになるんだ


どのような仕組みで


nが表示されるのかというと



2回目の

c = fgetc(fp);


を実行して


読み取った1バイトのデータ(アスキーコード)


%c出力変換指定子

を用いて


printf("%c", c);


実行したら


nが表示されたというわけなんだ


ハの文字コードの残り半分の1バイト分のデータは


nのアスキーコードだったというわけなんだね」


ずっと前のプログラム


👇

#pragma warning(disable: 4996)

#include <stdio.h>

int main(void) {


FILE *fp;

fp = fopen("TEN-GOGO-C-language.txt", "r");

if (fp == NULL) {

printf("ファイルオープンに失敗しましたよ~ん\n");

return -1;

}

else printf("Hello!ファイルオープンに成功しましたよ~ん\n");


int c;

c = fgetc(fp);


printf("%c", c);


fclose(fp);

return 0;

}


ビルド実行結果


Hello!ファイルオープンに成功しましたよ~ん


👆

・が表示されたのは


c = fgetc(fp);


printf("%c", c);


を実行して


ハの文字コードの半分の1バイト分のデータを読み取ったんだけど


その1バイト分のデータに対応する


画像データがないため



が表示されたんだね」




🌼  🌼


わあぁっ すごい


ソーラーさん


なんでそんなこと知ってるの?


まるで時空を飛び越えてここに来たみたいね


🌻  🌻

  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る