ハードディスク内に作成したファイルをオープンモード"r"で開きデータを読み込んでみます 別versionで説明してみます

おきた?おきた?😊



ソーラー「み~ん、み~ん」




🌞ソーラーさん もう ネタフリ得意なんだから🌞



ソーラー「はは ばれちゃった」



🌻  🌻

ハードディスク内に作成したファイルに新規書き込みできるよう


ファイルを開く


オープンモード"w"



ハードディスク内に作成したファイルに追加書き込みできるよう


ファイルを開く


オープンモード"a"



につづき



ハードディスク内に作成したファイルに保存されたデータの読み込みのみ


できるよう


ファイルを開く


オープンモード"r"


も紹介します。



オープンモード"r"では 


以前に


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


保存されたデータを


コンピュータのメモリに読み取りのみができる状態に


ファイルを開く


(ファイルポインタ変数fpを使ってファイルにアクセスできる状態にする)


ことができます。


ですので


fprintf関数などをつかって


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


データを書き込むことはできません


データの書き込みはできないのですが


コンピュータのメモリにハードディスク内のデータを


読み取ることはでき


読みとったハードディスク内のデータは


コマンドプロンプト画面にprintf関数をつかって


表示することができます。


これも試してみる?



   🌻     🌻


ソーラー「わあおぉう!」


🌻


何かになりきっている・・・


🌻


ソーラー「あ・・、お願い」


🌻


とりあえず


復習もかねてみようよ。


まずはオープンモード"w"で


ハードディスク内のTEN-GOGO-C-language.txtファイルを開き


ハードディスク内のTEN-GOGO-C-language.txt内に


保存されていたデータを初期化(消去)して


新たに


TEN-GOGO-C-language.txt内に


数値データ


1

2

3

4

5


を書きこんでみようよ


このとき


12345や1,2,3,4,5ではなくて


1

2

3

4

5



データをTEN-GOGO-C-language.txtファイルに保存したいんだけど・・


どう?


難しい?


🌼



ソーラー「はひ 簡単です


fprintf(fp,"%d\n",1);

fprintf(fp,"%d\n",2);

fprintf(fp,"%d\n",3);

fprintf(fp,"%d\n",4);

fprintf(fp,"%d\n",5);


のように


fprintf関数にエスケープシーケンス\nを使って


ソースコードを記述すれば


1

2

3

4

5


のように


1行ずつ改行して


ハードディスク内の


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


1

2

3

4

5


を保存することができるはずだよ


そして


fprintf(fp,"%d\n",1);

fprintf(fp,"%d\n",2);

fprintf(fp,"%d\n",3);

fprintf(fp,"%d\n",4);

fprintf(fp,"%d\n",5);


を見ても分かるように


数値データ

1

2

3

4

5



"%d\n"に格納されてから


ファイル構造体に格納されています。


つまり


文字列データ

"1"

"2"

"3"

"4"

"5"


として


メモリに格納されるんだね


ファイル構造体を通して


文字列データ


"1"

"2"

"3"

"4"

"5"



メモリに格納されたなら


ハードディスク内の


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


文字列データ

"1"

"2"

"3"

"4"

"5"

が保存されるわけだね。」


🌻  🌻


そのプログラムは、こうなるのかな?


#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");


fprintf(fp,"%d\n",1);

fprintf(fp,"%d\n",2);

fprintf(fp,"%d\n",3);

fprintf(fp,"%d\n",4);

fprintf(fp,"%d\n",5);


fclose(fp);

return 0;

}


コンパイル結果(EAZY IDECの場合)

ビルド結果(Visual Studioの場合)


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


ソーラー「TEN-GOGO-C-language.txtファイルをオープンモード"w"


で開き


文字列データ

1

2

3

4

5


を書き込み


そしてクローズできました


あとは


ハードディスクの


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


文字列データ

"1"

"2"

"3"

"4"

"5"



保存されているか確認、確認。


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


PC内で検索して


中身を確認してみると


おお


ちゃんと改行されて


1

2

3

4

5


が きれいに1行ずつならんで保存されてる


この

1

2

3

4

5

コンピュータが扱うとき

1

2

3

4

5


コンピュータには

文字列データ

"1"

"2"

"3"

"4"

"5"


と認識されます」



🌻       🌻


それでは


文字列データ


"1"

"2"

"3"

"4"

"5"


TEN-GOGO-C-language.txtファイルに保存し、準備が整ったところで


オープンモード"r"で


再び


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


を開いて


fscanf関数をつかって


TEN-GOGO-C-language.txtファイルに格納された


文字列データ


"1"

"2"

"3"

"4"

"5"


メモリに格納し


さらにそれらの文字列データ

"1"

"2"

"3"

"4"

"5"


から


1

2

3

4

5


とりだして


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

に格納し


配列変数に格納された


1

2

3

4

5



printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

printf("%d\n",hairetu[3]);

printf("%d\n",hairetu[4]);

を使って


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


それには


次のようにプログラムを記述します


#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 hairetu[5];


fscanf(fp,"%d",&hairetu[0]);

fscanf(fp,"%d",&hairetu[1]);

fscanf(fp,"%d",&hairetu[2]);

fscanf(fp,"%d",&hairetu[3]);

fscanf(fp,"%d",&hairetu[4]);


printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

printf("%d\n",hairetu[3]);

printf("%d\n",hairetu[4]);


fclose(fp);

return 0;

}


コンパイル結果(EAZY IDECの場合)

ビルド結果(Visual Studioの場合)


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

1

2

3

4

5


🌻  🌻  🌻



ソーラー「コマンドプロンプト画面に


1

2

3

4

5



表示できてるね。


ねえ😊きみ、


これ、どのような仕組みでTEN-GOGO-C-language.txtファイルから


文字列データ

"1"

"2"

"3"

"4"

"5"


がとりだされ


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


1

2

3

4

5

が表示されているの?」


🌻   🌻


このプログラムを詳しくみていく?


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


に保存されている


文字列データ

"1"

"2"

"3"

"4"

"5"


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


このプログラムでは


ファイルポインタ変数宣言とfopen関数の設定


FILE *fp;

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


がおこなわれて


ファイル構造体が作製され


ファイルポインタ変数fpを使って


TEN-GOGO-C-language.txtファイル内に保存されている

文字列データ

"1"

"2"

"3"

"4"

"5"


読み取ることができるようになります


fscanf(fp,"%d",&hairetu[0]);

fscanf(fp,"%d",&hairetu[1]);

fscanf(fp,"%d",&hairetu[2]);

fscanf(fp,"%d",&hairetu[3]);

fscanf(fp,"%d",&hairetu[4]);

が実行されると


まず


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


に保存されている文字列データ


"1"

"2"

"3"

"4"

"5"



ファイル構造体を通して


コンピュータのメモリに


文字列データ

"1"

"2"

"3"

"4"

"5"

のまま


格納されます。




int hairetu[5];



おこなうことにより


メモリに格納されている


文字列データ

"1"

"2"

"3"

"4"

"5"

から

とりだした

数値データ

1

2

3

4

5


格納するための


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


を用意しています


その


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


メモリに格納された

文字列データ

"1"

"2"

"3"

"4"

"5"

から

取り出された

数値データ

1

2

3

4

5


が格納されます😊


あとは

printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

printf("%d\n",hairetu[3]);

printf("%d\n",hairetu[4]);


が実行されると


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

1

2

3

4

5

が表示されます



このプログラムでは


配列宣言


int hairetu[5];を行い


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


を5つ用意しました。


最終的に


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


に保存されている文字列データ

"1"

"2"

"3"

"4"

"5"

から


数値データ

1

2

3

4

5


取り出されて


配列変数に格納されるのですが


数値データ

1

2

3

4

5


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

1

2

3

4

5

と格納されていました。


fscanf(fp,"%d",&hairetu[0]);

fscanf(fp,"%d",&hairetu[1]);

fscanf(fp,"%d",&hairetu[2]);

fscanf(fp,"%d",&hairetu[3]);

fscanf(fp,"%d",&hairetu[4]);


が実行されると


1行に格納されているデータごとに


配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


にデータが格納されていくシステムとなっています


配列変数

hairetu[0]には1

hairetu[1]には2

hairetu[2]には3

hairetu[3]には4

hairetu[4]には5


という具合にです。



ハードディスクのファイルの


1行目から取り出された数値1が


hairetu[0]にとりこまれたなら


同時に


2行目の数値2が


hairetu[0]には取り込まれたりはしないのです


そうして


配列変数に


hairetu[0]=1

hairetu[1]=2

hairetu[2]=3

hairetu[3]=4

hairetu[4]=5


と格納された数値は


printf("%d\n",hairetu[0]);

printf("%d\n",hairetu[1]);

printf("%d\n",hairetu[2]);

printf("%d\n",hairetu[3]);

printf("%d\n",hairetu[4]);


が実行されると


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


1

2

3

4

5

と表示されます


それでは次に

fscanf関数の仕組みを


今のプログラムの命令文


fscanf(fp,"%d",&hairetu[0]);

fscanf(fp,"%d",&hairetu[1]);

fscanf(fp,"%d",&hairetu[2]);

fscanf(fp,"%d",&hairetu[3]);

fscanf(fp,"%d",&hairetu[4]);


をつかって説明してみます。


fscanf関数の第1引数にはファイルポインタ変数fpが記述されています。


fpは


ファイルポインタ変数宣言とfopen関数の設定


FILE *fp;

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


がおこなわれたときのファイルポインタ変数fpです。


fscanf関数の第1引数に


ファイルポインタ変数宣言により


作製されたファイルポインタ変数fpを記述しなければ


fscanf関数をつかって


TEN-GOGO-C-language.txtファイルに格納されている文字列データ


"1"

"2"

"3"

"4"

"5"

から

数値データ

1

2

3

4

5


取り出して

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


に格納することはできません。


fscanf(fp,"%d",&hairetu[0]);


のfpの代わりに


fscanf(sp,"%d",&hairetu[0]);

のように


spと記述してしまうと


Visual Studioの場合


エラー (アクティブ) E0020 識別子 "sp" が定義されていません



ビルドエラーが生じます。


spはファイルポインタ変数宣言されていないので


コンパイラはspが何のことなのか判断できないので


機械語に翻訳できないというわけです


fscanf(fp,"%d",&hairetu[0]);

fscanf(fp,"%d",&hairetu[1]);

fscanf(fp,"%d",&hairetu[2]);

fscanf(fp,"%d",&hairetu[3]);

fscanf(fp,"%d",&hairetu[4]);


が実行されると


まず


ファイル構造体をとおして


TEN-GOGO-C-language.txtファイルに格納されている文字列データ

"1"

"2"

"3"

"4"

"5"

"1"

"2"

"3"

"4"

"5"

のまま

コンピュータのメモリに格納されます




🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞




            そこで問題です‼💖




🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞




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


文字列データ

"1"

"2"

"3"

"4"

"5"



保存されているとします


そのプログラムは以下のようになります


#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");


fprintf(fp,"%d\n",1);

fprintf(fp,"%d\n",2);

fprintf(fp,"%d\n",3);

fprintf(fp,"%d\n",4);

fprintf(fp,"%d\n",5);


fclose(fp);


return 0;

}




        fscanf(fp, "%d", &hairetu[0]);


が実行されると


ハードディスクのTEN-GOGO-C-language.txtファイルに保存されている


文字列データ"1"は


ファイルポインタ変数fpを使って


文字列データ"1"のまま


メモリに格納されます。


*fpは


文字列データ"1"を格納しているメモリのアドレスを格納しています。


そして


文字列データ"1"から数値データ1だけが取り出されて


配列変数hairetu[0]に格納されます。


なぜ


文字列データ"1"から数値データ1だけが取り出されて


配列変数hairetu[0]に格納することができるのかな?


どういう仕組みになっているのかな?


以下のプログラムの👉


#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 hairetu[5];


fscanf(fp, "%d", &hairetu[0]);


printf("%d\n", hairetu[0]);


fclose(fp);

return 0;

}


コンパイル結果


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

1



👉の中の


命令文


printf("%d\n", hairetu[0]);


の実行結果が

1

となっていることからも

hairetu[0]に格納されているのは


文字列データ

"1"


でなく


数値データ1であるのは間違いないとおもうんだけど・・・


🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞🌞




       🌞楽しいね ソーラーさん🌞

    




     🌞なぜだか  わっかる~かな うふふふ🌞



ソーラー「あ、ぼく わかっちゃったかな」





         🌞えぇ!もう?🌞






ソーラー「お話は


数値データ

1

2

3

4

5


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


次のプログラムを用いて


保存したときにさかのぼります。」


#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");


fprintf(fp,"%d\n",1);

fprintf(fp,"%d\n",2);

fprintf(fp,"%d\n",3);

fprintf(fp,"%d\n",4);

fprintf(fp,"%d\n",5);


fclose(fp);


return 0;

}


ソーラー「このプログラムが実行されると


数値データ

1

2

3

4

5



1行ごとに改行されて


TEN-GOGO-C-language.txtファイルに保存されます。


正確には保存されたように見えるかな ははっ(´▽`*)


数値データ

1

2

3

4

5


fprintf(fp,"%d\n",1);

fprintf(fp,"%d\n",2);

fprintf(fp,"%d\n",3);

fprintf(fp,"%d\n",4);

fprintf(fp,"%d\n",5);


が実行されると


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


もう数値データでなく


文字列データ

”1”

”2”

”3”

”4”

”5”

として保存されます。


つまり


TEN-GOGO-C-language.txtファイルの中身を確認したとき


表示されている

1

2

3

4

5


もう数値データでなく文字列データとなっている


コンピュータにはそう認識されるんだね。


その状態を経て


fscanf(fp, "%d", &hairetu[0]);

fscanf(fp, "%d", &hairetu[1]);

fscanf(fp, "%d", &hairetu[2]);

fscanf(fp, "%d", &hairetu[3]);

fscanf(fp, "%d", &hairetu[4]);


が実行されると


数値データ

1

2

3

4

5

でなく


文字列データ


"1"

"2"

"3"

"4"

"5"



ハードディスクのTEN-GOGO-C-language.txtファイルから


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


コンピュータのメモリに格納されるんだ


それはおいておいて


fscanf(fp, "%d", &hairetu[0]);



よく見てみて


ダブルクォーテーションの中に%d出力変換指定子がもちいられているね。


fscanf(fp, "%d", &hairetu[0]);


が実行されると


*fpが格納しているアドレスのメモリに格納されている


文字列データ"1"でなく


整数値データ1が


アドレス&hairetu[0]のメモリにあてて


つまり


配列変数hairetu[0]に格納されるんだよ。


*fpが格納しているアドレスのメモリに格納されているのは


文字列データ"1"なので


配列変数hairetu[0]に格納されるのは


数値データ1でなく文字列データ"1"なのではと思われるかもしれません。


また


文字列データ"1"は


配列変数hairetu[0]に格納できないと思われるかもしれません。



どちらも その通りなんです


その通りでなおかつ(笑)😊


配列変数hairetu[0]に格納されるのは


整数値データ1となります。


fprintf(fp,"%d\n",1);


が実行されると


ファイル構造体をとおして


数値データ1が


文字列データ"1"


としてメモリに格納されました


それと同様に


fscanf(fp, "%d", &hairetu[0]);


が実行されると


逆に


ファイル構造体をとおして


メモリに格納されている


文字列データ"1"



数値データ1


として


配列変数


hairetu[0]


に格納されます


言い換えると


fprintf(fp,"%d\n",1);


が実行されたときは


まず


ファイル構造体をとおして


数値データ1が


"%d\n"の%d出力変換指定子の部分にとりこまれ


文字列データ"1"として


メモリに格納されます


数値データ1は


"%d\n"


のはたらきにより


1から"1"へ


数値データ1から


文字列データ"1"


としてメモリに格納されたわけです


メモリに格納された


文字列データ"1"



そのまま


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


文字列データ"1"


として保存されます



同様に


fscanf(fp, "%d", &hairetu[0]);


が実行されると


まず


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


に保存されている


文字列データ"1"


ファイル構造体を通して


メモリに


文字列データ"1"のまま格納されます


その後

fscanf(fp, "%d", &hairetu[0]);


の"%d"のはたらきにより


メモリに格納された文字列データ"1"


から


整数値1だけが取り出されて


配列変数


hairetu[0]


に格納されます


実はこれと似たようなことは


たくさんやってきたんだよ


fscanf(fp, "%d", &hairetu[0]);



ちょうど


scanf("%d",&a);


と似たような関係となっています


両方ともscanf関数ですね。


scanf("%d",&a);


が実行されて


ユーザから1がコマンドプロンプト画面に打ち込まれたとします


コマンドプロンプト画面に打ち込まれたデータは


文字列データ"1"と認識されるのですが


scanf("%d",&a);



"%d"


のはたらきにより


整数値1だけが変数aに格納されるというわけです



fscanf(fp, "%d", &hairetu[0]);


では

*fpの格納しているアドレスのメモリ


に格納されている文字列データ"1"から


"%d"


のはたらきにより


整数値1だけをとりだして


配列変数hairetu[0]に格納していたけど仕組みは全く同じだね。




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

作者を応援しよう!

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

応援したユーザー

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