fclose関数にはファイルを閉じるという機能のほかに ファイルの書き込みモード、読み込みモードを解除するという面も持っています

同じプログラム内で fprintf関数を使って保存された数値を fscanf関数を使って配列に取り込むにはデータを保存後1度ファイルを閉じて書き込みモードを解除する必要があります。

ソーラー 「オープンモード"w+"の読み取り機能に関しては


なんか 微妙な考察結果となったね」



🌞ははは🌞


        🌞ははは🌞


ソーラー

「それではっっ 


ちょっと応用をきかせて


まっさらで何も保存されていない


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


fprintf関数を使って

数値

1

2

3

4

5

保存し


保存した、そのすぐ後に fscanf関数を使って


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


fprintf関数を使って


保存されたばかりの数値


1

2

3

4

5


配列内にとりこみ


配列内に格納された


1

2

3

4

5


コマンドプロンプト画面にprintf出力表示できるかどうか


ためしてみよぉぉぉぉ」



   🌻みよぉぉぉぉおぉぉっ


ソーラー「まずは恒例の


次のプログラムを実行して


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


fclose(fp);

return 0;

}


コンパイル結果


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


ソーラー「PC内検索で


実際に


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


の中身を調べてみると


もろに美しい空白が広がっている


清々しいね。


準備完了🌞


そして次に

そのまっさらな

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



fprintf関数を使って


数値


1

2

3

4

5

保存し


そのすぐ後に fscanf関数を使って


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


保存されたばかりの数値


1

2

3

4

5


用意した配列に格納し


配列に格納された


1

2

3

4

5


コマンドプロンプト画面にprintf出力表示できるか


ためしてみます


そのプログラムは次のようになります。


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



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;

}


コンパイル結果


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

9

2

1703760

1964398416

1703808

(この値はコンピュータのメモリの使用状況によって異なってきます。)


ソーラー「


なぜぇ


数値

1

2

3

4

5

fprintf関数をつかって

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

格納したはずなのに


fscanf関数をつかって

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

数値

1

2

3

4

5


コマンドプロンプト画面にprintf出力表示したら


9

2

1703760

1964398416

1703808

(この値はコンピュータのメモリの使用状況によって異なってきます。)


になる???????


なぜ??

??」


🌻     🌻     🌻


くすっ

どうやら

fprintf関数が使われて

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

書き込みのみできる状態となっているのだけど


ファイルを閉じて

書き込みのみできる状態を解除しないから


fscanf関数が機能していない


だから

fscanf関数をつかって

配列宣言

int hairetu[5];

により

生成された配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

ハードディスク内に保存された数値データ

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]

格納されている数値


9

2

1703760

1964398416

1703808

(この値はコンピュータのメモリの使用状況によって異なってきます。)



printf出力表示されたんだね


🌻  🌻

ソーラー「そうだね


最終的には

このプログラムは


プログラムの最後で


fclose(fp);


が行われて


TEN-GOGO-C-language.txtファイルの書き込み状態が解除され


TEN-GOGO-C-language.txtファイルは閉じられてる状態になってるね。


そういえば


TEN-GOGO-C-language.txtファイルにデータが保存されることと


fclose(fp);


によって


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


によって


ちゃんと

数値データ

1

2

3

4

5


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


格納されたかどうかを調べてみよう🌞


PC内検索でTEN-GOGO-C-language.txtファイルを


検索してみると・・・


おお やっぱりかな


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

によって


1

2

3

4

5

が保存されてるね」



🌻あっ ほんとだ🌻


ソーラー「そして



TEN-GOGO-C-language.txtファイルが閉じられることと

TEN-GOGO-C-language.txtファイルにデータが保存されることとは

関係ないのでした。


fclose(fp);


はファイルが開かれている状態を解除するために


あるのです


っていうのも


なんか


おもいだしちゃったな


🌻そう、そうだった🌻


ソーラー「どうやったら??


同じプログラム内で


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

保存した直後


fscanf関数を使って

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

それらの

数値

1

2

3

4

5


配列宣言

int hairetu;

により生成された

配列変数

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

printf出力表示できるのかな・・・


つまり


fprintf関数を使うことにより


書き込みのみできる状態に🐤🐤🐤🐤🐤🐤🐤🐤🐤🐤🐤🐤開かれた


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

fscanf関数をつかって

格納されたデータを

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]

に格納できる


読み込みのみできる状態🐤🐤🐤🐤🐤🐤🐤🐤🐤🐤🐤🐤に開かれるように


変更したいというわけなんだね。



fprintf関数を使うことにより

書き込みのみできる状態となった

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

に保存されたデータは

その書き込みのみできる状態のままでは

fscanf関数をつかって

読み取りができない。


その

書き込みのみできる状態から

読み込みのみできる状態に

変更するには?」



🌻は~い\(^o^)/ 🌻


ソーラー「わっ 君、元気がいいね」


🌻こんなんでどうかな?


fprintf関数により

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

に保存されたデータ

1

2

3

4

5

fscanf関数をつかって配列に格納するには



          fclose(fp);


を実行して


1度、

fprintf関数を使用することにより

書き込みのみできる状態に開かれている

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


んだよね。


          fclose(fp);


を実行して


書き込みのみできる状態に開かれている

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

解除したあと


fscanf関数を使用すると


書き込みのみできる状態から読み込みのみできる状態に


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



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!ファイルオープンに成功しましたよ~ん

9

2

1703760

1964398416

1703808

(この値はコンピュータのメモリの使用状況によって異なってきます。)


を次のように書き換えればいいことに

なります。

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


/*TEN-GOGO-C-language.txtが書き込みのみできる状態


に開かれているのを解除しました*/


FILE *fp;


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

if(fp==NULL){

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

return -1;}


/*TEN-GOGO-C-language.txtファイルを閉じたので

そのままでは

TEN-GOGO-C-language.txtファイルに格納された数値データを


よみとることができない?


とおもい


再び

ファイルポインタ変数宣言とオープンモードの設定を行いました。


(Visual Studioをお使いの方は、

ファイルポインタ変数宣言

FILE *fp;

は記述しないでください

ビルドエラーになります

理由は後述します)*/



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;

}


コンパイル結果


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

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

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

が格納された後


fclose(fp);


を行い


書き込みモード


つまり


ファイルが書き込みのみできる状態で開かれている状態を


解除しないといけないというわけなんだね。


fclose(fp);


を行うと


書き込みモードを解除できるけど


このままではファイルが閉じられたままで


読み込みができないから


ふたたび

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


FILE *fp;

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


(Visual Studioをお使いの方は、FILE *fp;を記述しないでください

ビルドエラーになります

理由は後述します)


if(fp==NULL){

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

return -1;}


を行う必要があるんだね。

そして

今は 

読み込みも書き込みもできる


オープンモード"a+"で


TEN-GOGO-C-language.txtファイルが開かれたわけだけど


オープンモード"a+"が

読み込みモードになるか書き込みモードになるかは


つまり


読み込みのみできる状態にファイルが開かれるか

書き込みのみできる状態にファイルが開かれるか



最初に

読み込みできるfscanf関数を使うか

書き込みできるfprintf関数を使うかによって決まるので



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]);

の命令文が実行されると


オープンモード"a+"は

読み込みモードになります


つまり


読み込みのみできる状態にTEN-GOGO-C-language.txtファイルが


開かれることになります


そして


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]);

により

配列変数

hairetu[0]

hairetu[1]

hairetu[2]

hairetu[3]

hairetu[4]


fprintf関数によってたった今

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

数値

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

が表示される。


ということになるんだよ~~


🌻  🌻



ソーラー「やったね!まさにそのとおり」



🌻           


あははははは どう どう

ソーラーさん


🌻


ソーラー「おみごとです!


このように


         🐥同じプログラム内で🐤



fprintf関数を使って保存された数値を


fscanf関数を使って配列に取り込むには、


fprintf関数を使ってファイルにデータを保存したあと


1度

fclose関数によりファイルを閉じて


書き込みモードを解除し


再びファイルを読み込みモードで


開いて


fscanf関数を使用可能状態に


する必要があります。」




🌳  🌳  🌳


プログラム中に


(Visual Studioをお使いの方は、

FILE *fp;

を記述しないでください

ビルドエラーになります)


と記述されていました


FILE *fp;

を記述すると


Visual Studioでは


FILE *fp;が再定義されています


つまり


ファイルポインタ変数宣言が


重複して使用されていますという意味の

ビルドエラーが表示されます。


Visual Studioでは


同じ名前をつかった変数宣言を


2度おこなうことはできないのです


fclose(fp);

により

ファイルが閉じられているのに


FILE *fp;


を記述しないで


ファイルポインタ変数fpがしようできるの?


と思われる方もいるかもしれません。



ファイルポインタ変数宣言

FILE *fp;

fclose(fp);


なんの関係もなく独立している


つまり


fclose(fp);


がおこなわれても


ファイルにファイルポインタ変数fpを用いてアクセスできる状態が


閉じられるだけで


ファイルポインタ変数fpそのものが


消去されてしまうわけではありません


ですので


fclose(fp);

により

ファイルが閉じられても


ファイルポインタ変数宣言

FILE *fp;

によって

作製された


ファイルポインタ変数fpは機能しています。


ですので


FILE *fp;

2度実行する必要はないというわけです。



また


書き込みモードと

読み込みモードで


同じ


ファイルポインタ変数宣言

FILE *fp;


によって作製される


ファイルポインタ変数fp


が使用されても


大丈夫なの?


と思われる方もいるかもしれません。


ファイルポインタ変数宣言

FILE *fp;

により

作製された

ファイルポインタ変数fpには


ハードディスクに保存したいデータをメモリに格納するとき


また


ハードディスクのファイルデータを読み取ってメモリに保存するとき


そのメモリのアドレスが格納されます。


たとえば


ハードディスクのファイルにデータを保存する際


まず


メモリにそのデータは格納されます。


つづいて


TEN-GOGO-C-language.txtファイルデータを読み取って


メモリに格納するとき


ファイルポインタ変数fpには


そのメモリのアドレスが格納されるのですが


そのとき


ファイルポインタ変数fpには


そのメモリのアドレスが


           💖上書きして💖


格納されます。


ですので


1度

ファイルポインタ変数宣言

FILE *fp;


をおこなえば


そのファイルポインタ変数に


上書きして

メモリのアドレスが書き込まれることになるので


あらたに


ファイルポインタ変数宣言

FILE *fp;

を行う必要はありません。






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

作者を応援しよう!

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

応援したユーザー

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