広告
↓発売日:2018年09月22日↓
新品価格 |
前回までのファイル処理の方法だと数値の処理に関しては、変換が必要などちょっと手間がありましたよね。
今回はそんな時に便利な数値をそのまま書き込む関数を紹介します。
/*六日目 プログラム1*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main(){ int ary[5] = {12,256,333,1465,7}; FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL){ printf("ファイルオープン失敗\n"); exit(1); } fwrite(ary,sizeof(int),5,fp); fclose(fp); return 0; }
まずは指定したサイズを指定回数分書き込む「fwrite()」になります。
fwrite(元のデータ,サイズ,書き込む回数,書き込み先);
このように使います。
さきほどのプログラムでいうと
int ary[5] = {12,256,333,1465,7};
こちらの「int」の配列データを
fwrite(ary,sizeof(int),5,fp);
指定したサイズ「int」で5回「fp」に書き込んだという事になりますね!
結果を見てみると・・・、何が何だかワケわからんですね。
まあ、でもこれで前回までのようにテキストファイルとして目に見えるカタチで読み書きするのはできませんが、数値→文字などの変換の手間が省けます。
ではここは無事に書き込まれていると信じてこの「test.txt」から今書き込んだデータを同じように指定サイズずつ読み込んでみます。
/*六日目 プログラム2*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main(){ int ary2[5] = {0}; FILE* fp; int count; fp = fopen("test.txt", "r"); if (fp == NULL){ printf("ファイルオープン失敗\n"); exit(1); } fread(ary2,sizeof(int),5,fp); for(count = 0;count < 5;count++){ printf("ary2[%d] = %d\n",count,ary2[count]); } fclose(fp); return 0; }
「fwrite()」の対になる「fread()」になります。
実行結果を見ると無事に配列「ary2」に先ほどのデータを格納する事ができました!
使い方もほとんど変わりありません。
fread(読み込み先,サイズ,読み込む回数,元データ);
元データから指定サイズずつ決められた回数を読み込み先に読み込みます。
ちなみにあまり使わないと思いますが、配列ではなく一つの変数だけを使って読み書きしたい場合は
int suji = 100; fwrite(&suji,sizeof(int),1,fp); fread(&suji,sizeof(int),1,fp);
などのようにアンパサンドをつけて引数にアドレスを渡します。
構造体でも大丈夫です。
/*六日目 プログラム3*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> struct PLAYER{ char name[128]; int age; }; int main(){ struct PLAYER p[5] = { {"田中一郎",20}, {"佐藤二郎",12}, {"斎藤三郎",21}, {"鈴木四朗",22}, {"渡辺五郎",23}, }; FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL){ printf("ファイルオープン失敗\n"); exit(1); } fwrite(p,sizeof(struct PLAYER),5,fp); printf("struct PLAYERのサイズ = %d\n",sizeof(struct PLAYER)); printf("struct PLAYER × 5 = %d\n",sizeof(struct PLAYER) * 5); fclose(fp); return 0; }
ファイルの内容を見たトコロで相変わらず判読不能だと思いますのでここは「test.txt」のプロパティを見てファイルサイズを確認してみます。
見ると作成した構造体のサイズ×5で660バイトあるのが確認できますね。
では書き込まれてるとして同じように読み込んでみます。
/*六日目 プログラム4*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> struct PLAYER{ char name[128]; int age; }; int main(){ struct PLAYER copy[5]; FILE* fp; int count; fp = fopen("test.txt", "r"); if (fp == NULL){ printf("ファイルオープン失敗\n"); exit(1); } fread(copy,sizeof(struct PLAYER),5,fp); for(count=0;count<5;count++){ printf("名前:%s 年齢:%d\n",copy[count].name,copy[count].age); } fclose(fp); return 0; }
無事に読み込む事ができました!
これで複雑なカタチのデータも扱えそうですね!
ここまでで主だったファイル処理の関数の紹介は終わりました。
なにやらいろいろあったと思いますので改めてここで少しまとめてみましょう。
「fputs()」「fgets()」
「fprintf()」「fscanf()」
「fputc()」「fgetc()」
「fwrite()」「fread()」
こんな感じですかね。
もちろんこれが全てではないので、いろいろ工夫してそのデータに合うファイル処理の仕方を見つけてみてください!
ここまでで今回の話の9割は終わったのですが、せっかくなのであの意味不明な内容のファイルの中身を少しばかり解説したいと思います。
まあ、ほぼプログラミングに役立つ事はないので箸休め程度にと思ってください。
もしかしたら情報処理系の試験に少しは役に立つかもしれません。
広告
では手始めに最初のプログラムを少し変更した次のプログラムを実行してみてください。
/*六日目 プログラム5*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main(){ int ary[5] = {65,66,67,68,69}; FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL){ printf("ファイルオープン失敗\n"); exit(1); } fwrite(ary,sizeof(int),5,fp); fclose(fp); return 0; }
書き込む内容を文字コードにしてみました。
「A」の文字コードは「65」ですね。
「test.txt」の内容に注目です。
なんとなくそれっぽい内容になってますね。
隙間を挟みながら「ABCDE」
さらにこの隙間の個数に注目してみると「A???B???C???D???E???」みたいにちょうど3つ分ずつ空いているのがなんとなくわかりますでしょうか?
このコンパイラの設定では「int」のサイズは4バイトです。
そうなんです、その4バイトずつ書き込まれているという事なのです。
という事は書き込む数字を少し工夫すればその隙間の部分にも何かしら文字が現れそうですね。
今からそれをちょっとやってみたいと思います。
いちよう進数・バイト・ビットなんかの知識はあると仮定して話を進めます。
では書き込む手順ですが、まず書き込まれる4バイトを一つずつに分解します。
「1バイト」「1バイト」「1バイト」「1バイト」
みたいな感じですね。
これをさらに2進数にします。
「00000000」「00000000」「00000000」「00000000」
こんな感じです。
次に書き込みたい文字コードを別々に分けて当てはめます。
例えば「A」の文字コード「65」を2進数にすると「01000001」になるので
「01000001」「01000001」「01000001」「01000001」
そしたら後はこれをつなげたもの
「01000001010000010100000101000001」
これを10進数に戻すだけです。
これはWindows付属の電卓を使った方が早いです。
電卓を起動、表示タグからプログラマモードに切り替えてさきほどの数字を貼り付け、10進数に変換します。
「1094795585」という数字がでてきました!
それでは試しにこの数字を先ほどのプログラムに当てはめて表示してみましょう!
/*六日目 プログラム6*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main(){ int ary[5] = { 1094795585, 1094795585, 1094795585, 1094795585, 1094795585 }; FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL){ printf("ファイルオープン失敗\n"); exit(1); } fwrite(ary,sizeof(int),5,fp); fclose(fp); return 0; }
無事に「AAAA...AAAA」と表示されました!
ちょっと周りくどい手順でしたが、無事に表示する事ができましたね!
(16進数で文字コードを入力、例えばAの文字コード41を4つ並べて「41414141」と入力してこれを10進数に戻しても大丈夫です)
ではこの調子で例えば「ABCD」みたいに表示したい場合は
「01000001」「01000010」「01000011」「01000100」
のようにすれば良いのかと思うトコロですが、残念ながらこれは間違った結果になります。
同じようにこれをつなげて
「01000001010000100100001101000100」
10進数変換すると、
「1094861636」
になるので・・・、
/*六日目 プログラム7*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main(){ int ary[5] = { 1094861636, 1094861636, 1094861636, 1094861636, 1094861636 }; FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL){ printf("ファイルオープン失敗\n"); exit(1); } fwrite(ary,sizeof(int),5,fp); fclose(fp); return 0; }
「DCBADCBA...DCBA」と表示されてしまいました。
なんと言いますか・・・、思った事とまったく反対の順番で書き込まれた感じですよね。
これはそのパソコンのデータを書き込む時のクセのようなもので、この逆に配置していくクセの事をリトルエンディアンと言います。
(他にビックエンディアンなんていうのもあります。もし興味ある方はインターネット検索してみてください)
なので「ABCD」の順番で書き込みたい時はこの性質に考慮して
4番目「01000100」3番目「01000011」2番目「01000010」1番目「01000001」
このような順番にしてから10進数に戻してあげなければいけません。
「01000100010000110100001001000001」
↓
「1145258561」
/*六日目 プログラム8*/ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> int main(){ int ary[5] = { 1145258561, 1145258561, 1145258561, 1145258561, 1145258561 }; FILE* fp; fp = fopen("test.txt", "w"); if (fp == NULL){ printf("ファイルオープン失敗\n"); exit(1); } fwrite(ary,sizeof(int),5,fp); fclose(fp); return 0; }
無事に「ABCDABCD...ABCD」と書き込む事ができました!
ファイル書き込みひとつとってみても、そんなこんな感じの事を内部では行っていたのですね!
という事で以上でファイル書き込みの解説を終わりにしたいと思います。
ご清聴ありがとうございます。
では次回は好きなトコロからファイル読み書きするいわゆるランダムアクセスについてやっていきたいと思います。
広告
↓発売日:2016年02月29日↓
12歳からはじめる ゼロからのC言語 ゲームプログラミング教室 新品価格 |
↓発売日:2018年06月22日↓
新品価格 |
↓発売日:2018年03月09日↓
新品価格 |
↓発売日:2017年06月14日↓
新品価格 |
↓発売日:2018年05月21日↓
新品価格 |
↓発売日:2017年12月07日↓
新品価格 |
↓発売日:2017年02月08日↓
新・明解C言語で学ぶアルゴリズムとデータ構造 (明解シリーズ) 新品価格 |
↓発売日:2017年09月26日↓
新品価格 |