👆ハードディスクにデータを保存したり、ハードディスクから保存されたデータをよみこむシステムはどのようになっているかをご説明いたします

ファイルポインタ変数宣言とfopen関数の書式設定をおこないハードディスク内にデータを保存するためのファイルを作製します

ある日の午後、ソーラーは寝ぼけていました。



* * * * * * * * * * * * * * * * * * * * * * * *



さてさて、


今までプログラムを


作製しては、コンパイルし


今日の日課で


作製しては、コンパイルし


コマンドプロンプト画面に文字列や数値をprintf出力表示してきました。


そうやってC言語畑を耕してきたわけです。


充実した日々でした。


ですが・・・


文字列や数値などのデータを


ハードディスクにデータとして保存するということはできませんでした。


ソーラー「そういや、そうだった


文字列や数値をただコマンドプロンプト画面に


printf出力表示していただけだった。


ハードデイスク内にファイルをつくり


そのファイルにデータを保存できない


となると・・・


他のパソコンとデータのやりとりを


できないし


あとからファイルに保存されたデータを加工


もできない


まあ、そうなるよね。」


🌻  🌻

起きた?



そこで、これから


データを格納するファイルをハードディスク内に


つくりだしていきます。


ここで根本的なことなのですが


文字列などのデータを


コンピュータのハードディスクに格納すること



コンピュータのメモリに格納すること


とは違います


コンピュータのメモリに格納された文字列などのデータは


プログラムの実行の終了とともに


コンピュータのメモリ内からきえてしまいます


メモリに1時的に保存されているだけなのです。


そこで それらのデータをずっと記憶するために


ハードディスク内にファイルを作製し


それらのデータを保存するのです。


さあ、とりあえず


ハードディスク内にファイルを作製するプログラムを見ていきましょう。


ファイル名はTEN-GOGO-C-language.txtとしています。



統合開発環境 EAZY IDECをもちいる場合


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



#include <stdio.h>


int main(void){

FILE *fp;

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


return 0;

}


統合開発環境Visual Studioをもちいる場合


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


#pragma warning(disable: 4996)

#include <stdio.h>


int main(void){

FILE *fp;

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


return 0;

}



統合開発環境Visual Studioの場合はこのように


統合開発環境 EAZY IDECの場合のプログラムの冒頭に


#pragma warning(disable: 4996)をお付けください


このように記述しなければ


統合開発環境Visual Studioはプログラム内の


fopen関数を使用できないのです。


なお、この#pragma warning(disable: 4996)のついたプログラムは


統合開発環境EAZY IDECでも実行することができます。


また

FILE *fp;

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

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


と記述しても構いません


FILE *fp;

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

の方が良く使われる表記法となっています。



このプログラムにより


ハードディスク内に

TEN-GOGO-C-language.txtという名のファイルを


作製することができます。


ここで登場するのが


ファイルポインタ変数fpなんです。


このソースコードの中の


FILE *fp;


はfpのファイルポインタ変数宣言とよばれます。


FILE *fp;


においてfpはファイルポインタ変数とよばれます。


ファイルポインタ変数名がfpとなっていますが


fpときまっているわけではありません。


Fpでもrpでもなんでもよいのです


自由にファイルポインタ変数名をつけることができます。


ハードディスク内にファイルを作成するためには


このプログラムのようにまず


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


FILE *fp;


をおこないます。


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


FILE *fp;


の次に記述されている命令文


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


のなかの


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


return 0;

}


が実行されると


ハードディスク内に


TEN-GOGO-C-language.txtファイルが作製されますが


同時に


ファイル構造体というものも作製されます。


ハードディスク内の

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


保存したいデータは


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


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


ファイル構造体はデータを保存するための型の役割を果たしています。


あるいは逆に


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


データを読み取りたいときは


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


データは


まず


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


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


コンピュータのメモリに格納されたそのデータは


printf関数などをつかって


コマンドプロンプト画面に表示することができます。


つまり


読み込み、書き込み


ともに


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


コンピュータのメモリに


データは格納されています。



ここでファイルポインタ変数fpの役割について考えてみます。



ハードディスク内に作成されたTEN-GOGO-C-language.txtファイルに


文字列などのデータを保存したいとき


それらの文字列データは


1時的に


       🌻ファイル構造体を通して🌻



       🌻コンピュータのメモリに🌻


格納されます。



その後


保存したい文字列などのデータは


ハードディスク内に作成された


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


保存したい文字列などのデータは


とりあえず


メモリに格納されることになるのですが


その文字列データに対応した値を


*fpは格納することになります。


(ファイルポインタ変数fpにではありません *fpにです)


また逆に


ハードディスク内に作成されたTEN-GOGO-C-language.txtファイル内に


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


コマンドプロンプト画面に表示したいときは


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


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


まず



    🌻ファイル構造体を通して🌻



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


そのコンピュータのメモリに格納されたデータを利用して


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


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


保存されている文字列データが表示されるのです。


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


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


1時的にメモリに格納されることになるのですが


その文字列データに対応している値を格納しているのも


*fpなのです。



ソーラー「お、おおう」


🌻おきた・・


データがメモリに格納されるごとに


*fpに格納されている値は変化していきます


しかし


ファイルポインタ変数に格納されている値は


一定のままで変化しないのです😊


ソーラー「ほえぇ?」


🌻  🌻


まだ ねてる・・・


ここら辺はソーラーさんが寝ぼけているので


詳しくは後ほど語りましょう。


ファイルポインタ変数fpの意味がだいたいわかったところで


次は


fopen関数の設定


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


について


考察していきましょう。


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



ソースコードに記述されていると何か難しく感じますね。


しかし


意味が分かればとても簡単な命令文だということがわかります。



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


ここで記述されているfopenは関数なのです。


ダブルクォーテーション""で囲まれた"TEN-GOGO-C-language.txt"は


fopen関数の第1引数であり


""で囲まれた”w”は


fopen関数の第2引数となっています


第1引数


に"TEN-GOGO-C-language.txt"と記述することにより


ハードディスク内に作成されるファイルの


ファイル名が TEN-GOGO-C-language.txt ときめられます



fopen関数の第2引数には"w"と記述されていますが


この"w"はオープンモード"w"とよばれ


命令文


FILE *fp;

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



により


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


作製されたとき


TEN-GOGO-C-language.txtファイルを新規書き込み可能状態で


開くためにもちいられます。


(そのことはすぐ💖に語られます)


また命令文


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



すでに


ハードディスク内に


TEN-GOGO-C-language.txtファイルが作製されていた場合


ハードディスク内に作製されていた


TEN-GOGO-C-language.txtファイルを新規書き込み可能状態で


開くという命令文でもあるのです。



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


ファイルが開かれるとは


ハードディスクに作製されたファイルにアクセス可能な状態にする


ことを意味しています


(ファイルが開かれると


ハードディスク内に作製されたファイルのデータは


ファイル構造体を通してメモリに格納することができるようになります


また


ハードディスク内に作製されたファイルに保存するためのデータを


ファイル構造体を通してメモリに格納することができるようになります)



ファイルが閉じられるとは


ハードディスク内に作製されたファイルに


アクセスができない状態になる


ということを意味しています


(ファイルが閉じられると


ファイル構造体はきえてしまい


ファイル構造体


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


ハードディスク内に作製されたファイルのデータも


ファイル構造体



とおしてメモリに格納されたハードディスク内に作製されたファイル


に保存するためのデータも


消去されます。


ファイルポインタ変数fpも消去されます。


このとき


ハードディスク内に作製されたファイルのデータが


消去されるわけではありません。ご注意ください


このことは後のエピソードで


もっと優しく詳しく記述されます


そして


どのような状態でファイルを開くかを指定するために


fopen関数の第2引数にオープンモードが書きこまれます。


オープンモードには

ハードディスク内の

ファイルを新規書き込みできる状態に開くオープンモード”w”


ファイルを前に保存したデータの後に

追加書き込みできる状態に開くオープンモード”a”


ファイルに一切書き込むことができず

ファイルに以前保存されたデータを読み取りのみできる状態に開く

オープンモード”r”


などなど・・・


があります。

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


もうすこしオープンモードについて


説明してみます


ファイルを新規書き込みできる状態に開くオープンモード”w”



新規書き込みとは 


今までにファイルに記憶されたデータをまっさらに消して


新たにゼロから


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


データをかきこむことを表しています


wはwrite(書き込む)の略というわけです




オープンモード"r"をつかって


TEN-GOGO-C-language.txtファイルが開かれたときは


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


新たにデータの書き込みはできず


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


保存されているデータの読み込みしかできません


rはread(読み込む)の略です



オープンモード”r”はfopen関数内で


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


のように記述され


TEN-GOGO-C-language.txtファイルに以前保存されたデータを


読み取りのみできる状態にファイルを開くよう指定するはたらきがあります。


オープンモード”r”で

ハードデイスク内の

TEN-GOGO-C-language.txtファイルを開いた場合


TEN-GOGO-C-language.txtファイルに新たにデータを一切書き込むことはできません。


また

この命令文

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

には

ハードディスク内に

TEN-GOGO-C-language.txtという名のファイルがなければ


新たにTEN-GOGO-C-language.txtという名のファイルを作製し


オープンモード"r"でTEN-GOGO-C-language.txtファイルを開くという


はたらきもあります。


ですので


ハードディスク内に

TEN-GOGO-C-language.txtという名のファイルがなく


オープンモード"r"で


新たにTEN-GOGO-C-language.txtという名のファイルを作製し


TEN-GOGO-C-language.txtファイルを開いた場合


TEN-GOGO-C-language.txtファイルにはデータが保存されていないので


コンピュータのメモリに


ファイル構造体を通して


何も読み取ることができないということになります。


お話はかわって(^_-)-☆


オープンモード"w"を使った


FILE *fp;

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

が記述された

プログラム


#pragma warning(disable: 4996)

#include <stdio.h>


int main(void){

FILE *fp;

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


return 0;

}

が実行されると


ハードディスク内に


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


が作成され


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


新規書き込み可能な状態となって開かれていることはわかりましたが


コンパイル結果は


コマンドプロント画面に


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


が表示されるのみで


他にはにはなにも表示されません


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

実はfopen関数は


今の


オープンモード"r"の説明でものべられたように


ハードディスク内に新たに


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


新規作成するためだけに


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


と記述してもちいられるのでなく


ハードディスク内に


すでに作製されたTEN-GOGO-C-language.txtファイルを


オープンモード"w"で再び開くときも


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


のように記述してもちいられます。


そして


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


が実行されると


オープンモード"w"で


TEN-GOGO-C-language.txtファイルが開かれるので


今までにTEN-GOGO-C-language.txtファイルに記憶されたデータは


まっさらに消され初期化された状態になります。


ですので


新たにゼロからTEN-GOGO-C-language.txtファイルにデータをかきこむ


ことになります。


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


ここでハードディスク内に作成された


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


末尾についている.txtは


このファイルが文章データのみを保存していることを


表すためにつけられています


このように記述しておくと


後で何のファイルかわかるので 管理がしやすいのです。



ソーラー

「面白動画だとファイル名の最後に


.mp4

.wwv  等が


画像データなら


.jpeg 等が記してあるのはよくみかけるよね。


.mp4

.wwv をみれば


このデータは動画だというのがすぐにわかるよね


.txtと記述してないと


このファイルは動画を保存しているのか?

画像データを保存しているのか?


それとも

文章データを保存しているのか?


判断出来ないね。


それにしても プログラムを実行して


ハードディスク内にファイルを作製


新規書き込みできる状態にしたのに


コマンドプロンプト画面になにも表示されないってのは


さみしいね・・・?」


🌼

そう,そう


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


ハードディスク内のどこかに作成されていて


新規書き込みできる状態に開かれているのですが


きちんとファイルが作成されて


新規書き込みできる状態にファイルが開かれているかどうかは

(ファイルにアクセスできる状態になっているかどうかは)


コマンドプロンプト画面になにも表示されていない今の状態


からではわからないんだね。


それはひとまずおいておいて


そうしてハードディスク内に作成され、新規書き込み、あるいは、


読み込み可能状態に開かれた


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


を閉じるには


fclose関数をもちいて


fclose(fp);と表記します。


TEN-GOGO-C-language.txtファイルを開いたままで


つまり


ハードディスク内の


TEN-GOGO-C-language.txtファイルのデータにアクセスできる


状態のままにしておくと


つまり


ファイル構造体を作製したままほっておくと


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


メモリにデータが格納されるおそれがあるのです。


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


メモリにデータが格納された瞬間に


ハードディスク内のファイルにそのデータは保存されることになります。


このように


fclose関数をもちいて


ハードディスク内のファイルにアクセスできないようにする


fclose(fp);


を実行しなければ


ハードディスクのファイルが書き換えられるなどの不具合が生じる可能性があるのです。


アドレスがわかればそのメモリ内のデータを書き換えることができるのは


ポインタ変数の所でもならった?ならった?どう?


ファイル構造体をとおしてメモリにデータは格納されるわけだけど


そのメモリのデータをかきかえるのは


それほど難しくはありません


メモリのデータが書き換えられる操作が行われると



ハードディスク内のファイルの保存されているデータも


書き換えられるんだね。


だから


fclose(fp);


を実行してファイルを閉じて


ファイル構造体を消去して


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


アクセスできない状態にするというわけです。



そのような理由から



fopen関数でハードディスク内のファイルを開いたら


fclose関数をファイルポインタ変数fpに


fclose(fp);


のように用いて


開いているファイルを


閉じるというきまりになっています。


そのようなわけで


FILE *fp;

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


でファイルをオープンする命令文を記述したら


セットでファイルをクローズする命令文

fclose(fp);

を記述することになります。


そのファイルを作製、開いてから、閉じるまでの


1連の流れのプログラムは次のようになります。


#pragma warning(disable: 4996)

#include <stdio.h>

int main (void){


FILE *fp;

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

fclose(fp);

return 0;

}


このプログラムをコンパイルすると



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


と表示されるのみで


他には何も表示されません


ですが


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


ファイルがコンピュータのハードディスク内のどこかに


作製されて


新規書き込み可能状態で開かれ


そして

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


一連の動作は


終了しています。


🌼




ソーラー「はいっ


さてっと ではでは


このプログラムで作成された


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


ハードディスクのどこに作製できてるのかな


ファイルのできている場所は?っと」




🌻  🌻


そうですね 気になりますね。


次のようにファイルポインタ変数宣言

👇

FILE *fp;

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


が実行されると


TEN-GOGO-C-language.txtと名前のついたファイルが


PCのハードディスク内に生成されています。


そこで


PC内のデータ検索欄にてTEN-GOGO-C-language.txt


を入力して検索してみると


TEN-GOGO-C-language.txtと名前のついたファイルが


みつけられます。


ソーラー「どれ🌞どれっ🌞と」


実際に


PC内のデータ検索欄にてTEN-GOGO-C-language.txtを


うちこみ


作製された


TEN-GOGO-C-language.txtを発見するソーラー。


ソーラー「なんと


C言語をつかって


パソコンのハードディスク内に


自分でファイルを作成できちゃった。」


🌻  🌻


おめでとう


ハードディスク内に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");

fclose(fp);

return 0;

}


コンパイル結果


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



TEN-GOGO-C-language.txtファイルを作成し閉じる


このプログラムをコンパイルしても


コマンドプロンプト画面には何も表示されません。


つまり コンパイル後


(*^-^*)コマンドプロンプト画面をみただけでは(#^.^#)


ファイルがハードディスク内に本当に作成できているか


どうかわかりません。


🌼


ソーラー「いいね(^_-)-☆」



🌻  🌻


ファイルに不具合がおこっていたり


あとから


以前に作製した

ファイルをオープンしようとしたときに


すでにファイルを削除してしまったりしていて


ファイル自体が存在していないこともありえます。


存在しないファイルを開いてデータを書きこんだり


存在しないファイルに保存されているデータを


読み込んだりすることはできないので


ファイルが正常にオープンできているかどうかを


コマンドプロンプト画面から確認できるようにする


作業をおこなう必要があります


fopen関数はファイルオープンに失敗するとNULL


というデータをファイルポインタ変数fpにかえすことになっています。


その特性を利用し


FILE *fp;

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

と命令文を記述したあと


ファイルが無事オープンできているかを確認するために


if(fp==NULL){

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

return -1;}

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


と命令文を表記しておきます。


🌳🌳🌳



fp==NULLを

fp=NULLと表記してはいけません


ここについては次のエピソードで詳しく述べます


🌳🌳🌳


また if(fp==NULL){

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

return -1;}

で記述される


return -1は プログラムの実行に


問題が発生したときに


main関数に0以外の戻り値を返す


というきまりによりつけられています。


0以外ならなんでもよいのですが-1を返すというのも


慣例ですね。


では、先程のプログラムに今の命令文


if(fp==NULL){

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

return -1;}

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



付け加えてコンパイルしてみると


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

}


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

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

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


と表示されます


これでTEN-GOGO-C-language.txtファイルが無事にオープンできる


つまり


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


アクセスできることが確認できました。


つまり このプログラムでは


オープンモード"w"で


ハードディスク内のファイルを新規書き込み可能な状態で


開き


ファイルが開かれたことも確認して


ファイルを閉じることができたというわけです。


さあ、これで


TEN-GOGO-C-language.txtが作成され


TEN-GOGO-C-language.txtにアクセス可能なことが確認できたので


これから


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


にデータを書き込んで保存することができますね。



🌼



ソーラー「データを保存か・・ほんと基本的だね。」



🌻  🌻

今の状態は


fclose(fp);


により


ファイルは閉じられています


再び ファイルを開きたいのですが


そのファイルのデータを読み込みだけしたくて


あとから書き込みできないようにファイルを開くには


後から詳しく述べますが


"w"の代わりに"r"を


次のソースコードのように


fopen関数の第2引数に記入します


FILE *fp;

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


このソースコードの記述のように


再び


TEN-GOGO-C-language.txtファイルを開くときには


普通は


以前


TEN-GOGO-C-language.txtファイルを作製するときにもちいた


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


FILE *fp

(実は後のエピソードでも述べられるように

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

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

ファイルポインタ変数gp

ファイルポインタ変数hp

でもなんでもよいのです


後ほど💖語られますが


さらにいうと


TEN-GOGO-C-language.txtファイルを再び開くときに


以前


TEN-GOGO-C-language.txtファイルを作製するときにもちいた


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


FILE *fp


で使用されたファイルポインタ変数fpを用いる必要すらありません


FILE *sp

FILE *rp

FILE *hp

のようにファイルポインタ変数名はなんでもかまいません)



以前


TEN-GOGO-C-language.txtファイルを作製するときに


fopen関数の第1引数に記述されていた


TEN-GOGO-C-language.txtを


fopen関数の第1引数に


もちいます。


オープンモードは


"w"

"r"

"a"

いずれか目的にかなうものを選びます。


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

作者を応援しよう!

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

応援したユーザー

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