ファイルポインタ変数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バイト分のデータに対応する
画像データがないため
・
が表示されたんだね」
🌼 🌼
わあぁっ すごい
ソーラーさん
なんでそんなこと知ってるの?
まるで時空を飛び越えてここに来たみたいね
🌻 🌻
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます