みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

fwrite文について

char型で宣言した配列の方はうまくいきましたが、構造体を用いたfwrite文がうまく出力されません。
どうしてでしょうか?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct ll{
char name[20];
int ten[3];
}list[3] = {
{"aaa", 11},
{"bbb",22},
{"ccc",33}
};


FILE *fpbin, *fpcsv;/*FILE構造体(グローバル変数)*/

void main(void)
{
char i[] = {'a','b'};

fpbin = fopen("data.txt","w");
//fwrite(&i,sizeof(char),2,fpbin);
fwrite(&list[0].name,sizeof(struct ll),2,fpbin);
fclose(fpbin);
}

投稿日時 - 2004-12-18 10:03:36

QNo.1131916

暇なときに回答ください

質問者が選んだベストアンサー

プログラムの想定動作がわからないのですが、
問題がいくつかあります。

(1)構造体配列の宣言の所、
struct ll{
char name[20];
int ten[3];
}list[3] = {
{"aaa", 11},
{"bbb",22},
{"ccc",33}
};

これは、charの方はいいのですが、intの配列の方が
正しく初期化されていません。

struct ll{
char name[20];
int ten[3];
}list[3] = {
{"aaa", {1,1,1}},
{"bbb",{2,2,2}},
{"ccc",{3,3,3}}
};
のように、入れ子の配列を使って初期化します。

(2)
fwrite(&list[0].name,sizeof(struct ll),2,fpbin);
のところ、.nameは不要で
fwrite(&list[0],sizeof(struct ll),2,fpbin);
とします。もっとも、指すアドレスは同じなので、
直さなくても動きますが…。

(3)出力ファイルをdata.txtとしています。
文法的にはtxtファイルという拡張子で問題ないのですが、
fwriteで出力されるものは基本的にバイナリファイルです。
これで書き出したものをテキストエディタで見ると、charの配列は読めるけれど、
intやdoubleなどの数値はコンピュータの内部状態のまま出力されるため、
意味不明な記号になります。
(fwrite()で書き込んだファイルは、基本的にfread()で
読み込むべきデータファイルです。)
バイナリファイルを読むときは「バイナリエディタ」というツールがあります。
必要ならばVectorあたりからダウンロードしてください。
テキストファイルとして書き込みたいのなら、
fwrite()ではなくてfprintf()などの関数を使います。

以上のことを参考にして、書き直してみてください。

投稿日時 - 2004-12-18 10:45:15

補足

詳しい解説ありがとうございます。おかげでよく分かりました。ところでfread()処理を行ってファイルから読んで表示させようとしたところ、文字の方はきちんと表示されましたが、数字の方が表示されません。
どうしてでしょうか?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct ll{
char name[20];
int ten[3];
}list[3] = {
{"aaa", {1,1,1}},
{"bbb",{2,2,2}},
{"ccc",{3,3,3}}
};


FILE *fpbin, *fpcsv; /*FILE構造体(グローバル変数)*/

void main(void)
{

fpbin = fopen("data","w+");
fwrite(&list[0],sizeof(struct ll),3,fpbin);

fread(&list[0],sizeof(struct ll),1,fpbin);
printf("p = %s ten = %d\n", list[0].name, list[0].ten);
fclose(fpbin);

}

投稿日時 - 2004-12-18 13:51:53

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

> printf("p = %s ten = %d\n", list[0].name, list[0].ten);

ここのところにある
list[0].ten
は、あくまで「int型の配列」であって、int型ではありません。
配列の中に入っているint型を表示させたいなら

printf("p = %s ten = %d\n", list[0].name, list[0].ten[0]);

のようにします。

配列に入っている値を三つとも表示するときは

printf("ten1 = %d, ten2 = %d, ten3 = %d\n", list[0].ten[0], list[0].ten[1], list[0].ten[2]);

のようにします。

投稿日時 - 2004-12-18 17:05:38

補足

返答ありがとうございます。きちんと表示されました。
ところで、fwriteとfreadの戻り値が正常時は第三引数に一致するとなっていますが、fwriteの方はきちんと表示されますが、freadの方が0となってしまいます。なぜでしょうか?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct ll{
char name[20];
int ten[3];
}list[3] = {
{"aaa", {1,1}},
{"bbb",{2,2}},
{"ccc",{3,3}}
};


FILE *fpbin, *fpcsv; /*FILE構造体(グローバル変数)*/

void main(void)
{
char i[] = {'a','b'};
int su;
fpbin = fopen("data.txt","w+");
//fwrite(&i,sizeof(char),2,fpbin);
su = fwrite(&list[0],sizeof(struct ll),3,fpbin);
printf("su = %d", su);
fpbin = fopen("data.txt","r");fclose(fpbin);
su = fread(&list[0],sizeof(struct ll),3,fpbin);
printf("su = %d", su);
printf("name = %s ten1 = %d, ten2 = %d\n",list[0].name, list[0].ten[0], list[1].ten[1], list[0].ten[2]);
fclose(fpbin);
}

投稿日時 - 2004-12-19 12:01:40

お礼

fwriteとfreadはバイナリファイルを扱うものなのでfpbin = fopen("data.txt","w+");ではなくfpbin = fopen("data","w+b");でした。freadの戻り値もきちんと表示されました。
どうもお騒がせしました。

投稿日時 - 2004-12-19 12:31:37

ANo.2

配列はlist[3]なのに、
書き出す個数が2になっています。

あと、#1の方が言われているように、
ちゃんと、int型のデータを初期化しておいた方が良いでしょうね。
読み出した時にゴミなのかデータなのかわかりませんから。

投稿日時 - 2004-12-18 11:15:54