• ベストアンサー

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

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

  • ベストアンサー
  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.1

プログラムの想定動作がわからないのですが、 問題がいくつかあります。 (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()などの関数を使います。 以上のことを参考にして、書き直してみてください。

yukikundesuyo
質問者

補足

詳しい解説ありがとうございます。おかげでよく分かりました。ところで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); }

その他の回答 (2)

  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.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]); のようにします。

yukikundesuyo
質問者

お礼

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

yukikundesuyo
質問者

補足

返答ありがとうございます。きちんと表示されました。 ところで、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); }

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

配列はlist[3]なのに、 書き出す個数が2になっています。 あと、#1の方が言われているように、 ちゃんと、int型のデータを初期化しておいた方が良いでしょうね。 読み出した時にゴミなのかデータなのかわかりませんから。

関連するQ&A

  • fwrite処理について

    fwrite処理を行っているのですが、うまくファイルに出力されません。どこがおかしいか分からない次第です。 返答のほど、よろしくお願いします。 #include <stdio.h> #include <string.h> #include <stdlib.h> struct ll{ long int bango; char name[20]; char denwa[15]; }; FILE *fpbin; /*FILE構造体(グローバル変数)*/ struct ll *memalloc(void); void main(void) { struct ll *p; p = memalloc(); fpbin = fopen("bin","w+b"); printf("追加するNo 名前 tel >\n"); scanf("%ld %s %s", &p -> bango, p -> name, p -> denwa); printf("%ld %s %s\n", p -> bango, p -> name, p->denwa); fwrite(p,sizeof(struct ll),1,fpbin); fclose(fpbin); } struct ll *memalloc(void) { struct ll *p; if ( (p = (struct ll *)malloc(sizeof(struct ll))) != NULL ){ return p; } printf("メモリの動的割当に失敗しました。\n"); exit (1); return p; }

  • リスト

    リスト構造にしたいのですがどうすればいいでしょうか。 #include <stdio.h> #include <stdlib.h> #include <string.h> struct toy { char name[10]; int number; struct toy next; }; /*プロトタイプ宣言*/ void omocha_toy(struct toy *x); int main( void ) { struct toy *x; if((x =(struct toy *)malloc(sizeof(struct toy))) == NULL) { fprintf(stderr,"エラー\n"); exit(1); } sprintf("x -> name,"Osarusan"); x->score = 12; omocha_toy(x); return 0; } void omocha_toy(struct toy *x) } printf("%s",x->name); printf("%d\n",x->number); } このプログラムで2つ目3つ目をリスト構造を使って作りたいんです。 お願いします。

  • 構造体内のポインタのポインタにアクセスするには?

    たとえば、 struct a { char **name } という構造体があったとして、 struct *a; a->name = malloc(sizeof(char *) * 3); としたときに、 for(i = 0; i < 3; i++){ a->name[i] = malloc(sizeof(char) * 10); } とするとエラーになります。 a->name配列の各要素をmallocするにはどうすればよいのでしょうか?

  • アルゴリズム 線形リスト

    最近リストについて習い始めました。入力したデータと同順に並ぶリストを作成しようと思い、コードを打ったのですが…動作中止の表示がでてしまいました。どこが間違っているのか、ずっと悪戦苦闘して組んでいるのですが、全く出口が見えてきません。何が間違えているのか、はたまた根本的に違うのか、ご指導して頂けると有難いです。 以下、コードです。 #include <stdio.h> #include <stdlib.h> #include <string.h> struct hito{ char name[20]; int age; struct hito *next; }; void main(void){ struct hito *p, *head, *dummy; char new_name[20]; int new_age; dummy = (struct hito *)malloc(sizeof(struct hito)); head = dummy; dummy->next = p; dummy = p; while (scanf("%s %d" , new_name, &new_age) != EOF) { p = (struct hito *)malloc(sizeof(struct hito)); strcpy(p->name, new_name); p->age = new_age; p->next = head; head = p; } while(p != NULL) { printf("\t%-20s %3d\n" , p->name, p->age); p = p->next; } }

  • fread処理について

    fread処理を用いてファイルの内容を取得した後、printf("%s\n", p);で参照してみるとaaa 1 21 333 bb 24 325 6 c 7 82 98とまとめてファイルの値を取得してしまいます。この取得した値をひとつずつ分けてNODEのnameとtenに格納しようとしているのですがうまくいきません。どうすればいいでしょうか? それと、第三引数で選択した値がレコードの個数とありますがすべて選択されてしまうのどうしてでしょうか? test.txtの中身 aaa 1 21 333 bb 24 325 6 c 7 82 98 #include <stdio.h> #include <string.h> #include <stdlib.h> #include<malloc.h> typedef struct{ /*出力レイアウト*/ char name[20]; int ten[3]; }RECORD; FILE *fpbin; /*FILE構造体(グローバル変数)*/ void main(void) { RECORD *p; p = malloc(1); fpbin = fopen("test.txt","r"); fread(p,sizeof(RECORD), 1, fpbin); printf("%s\n", p); }

  • c 言語初心者です。

    c 言語初心者です。 私は下記の構造体配列をつくりました。 しかしバッファオーバーランが起きてエラーが起きてしまいます。 ヒープ領域に問題があるのかもしれませんが、プログラム上どこに原因があるのかが良くわかりません。 どなたかよろしければ教えていただけないでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include<memory.h> struct s { int i; char name[25]; char huri[25]; char num[23]; }; void touroku(struct s *p); void hyouji(struct s *p); int main(void) { struct s data; touroku( &data ); hyouji( &data ); //data.num *= 1; /* dataはポインタではないのでドット演算子 */ hyouji( &data ); return 0; } /* 構造体のメンバを設定する */ void touroku(struct s *p) { int i=0; for(i=1;i<3;i++) { printf( "25文字以内の名前を入力して下さい\n" ); memset(p[i].name, 0, sizeof(p[i].name)); fgets( p[i].name,sizeof(p[i].name) , stdin ); if(strchr(p[i].name,'\n')==NULL)//バッファ処理 { while(getchar() != '\n'); } if(p[i].name[strlen(p[i].name)-1]=='\n')//改行解除 { p[i].name[strlen(p[i].name)-1] = '\0'; } printf("25文字以内のふりがなを入力してください\n"); memset(p[i].huri, 0, sizeof(p[i].huri)); fgets(p[i].huri,sizeof(p[i].huri),stdin); if(strchr(p[i].huri,'\n')==NULL)//バッファ処理 { while(getchar() != '\n'); } if(p[i].huri[strlen(p[i].huri)-1]=='\n')//改行解除 { p[i].huri[strlen(p[i].huri)-1] = '\0'; } printf( "整数を入力して下さい\n" ); memset(p[i].num, 0, sizeof(p[i].num)); fgets(p[i].num,sizeof(p[i].num),stdin ); if(strchr(p[i].num,'\n')==NULL)//バッファ処理 { while(getchar() != '\n'); } if(p[i].num[strlen(p[i].num)-1]=='\n')//改行解除 { p[i].num[strlen(p[i].num)-1] = '\0'; } } } /* 構造体のメンバを出力する */ void hyouji(struct s *p) { int i=0; for(i=1;i<3;i++) printf("%-8s %3s %3s %d\n" ,p[i].name , p[i].huri , p[i].num , i); puts("----------------------------------------------------------------"); return ; }

  • 構造体について

    凄く初歩的な質問で申し訳ありませんが… 入門書の構造体のところで 以下のようなプログラムの例がありました。 #include <stdio.h> struct seiseki { /* 構造体の宣言 */ int no; char name[20]; double average; }; int main(void) { int i; struct seiseki seito1, seito2[20]; /* 構造体変数と構造体配列の宣言 */ >char name[20] というのは、NAMEの領域を20文字 確保すると言うことですよね? >struct seiseki seito1, seito2[20] ここの箇所が分からないのですが seito2[20]の20というのは どうして20なのですか? NAMEだけではないので もっと大きな数字になるような気がするのですが… またseito1の方は どうして数字が何もないんですか? 考え違いをしているところを ご指摘して頂ければ幸いです。

  • fread処理がうまくいかない!!

    バイナリエディタでfwriteで書き込んだデータは確認できたのですがfread後のデータがきちんと表示されません。 どうしてでしょうか? #include <stdio.h> void main(void) { char i[] = {'a','b'}; char j[2]; FILE *fpbin; fpbin = fopen("data","wb+"); fwrite(&i,sizeof(char),2,fpbin); fpbin = fopen("data","rb"); fread(&j,sizeof(char),2,fpbin); printf("j = %c\n", j[0]); fclose(fpbin); }

  • 構造体とfscanf

    ファイルをfscanfを使って文字列を構造体に格納して読み込みたいのですが読み込み方の記述方法がわか りません。 どのようにしたら読み込めますか? 以下ソース ---ソース--- #include <stdio.h> #include <string.h> #include <stdlib.h> struct info //1回目の呼び出し方法 { char name[20]; char mb[20]; }deta; struct info2 //2回目の呼び出し方法 { char *name; char *mb; }deta2; struct info3 //3回目の呼び出し方法 { char *name[6]; char *mb[6]; }deta3; void main(void){ FILE *fp; fp=fopen("yasa.txt","r+"); while( !feof( fp ) ){ fscanf( fp, "%s %s",deta.name,deta.mb ); printf("%s %s\n",deta.name,deta.mb); } rewind( fp ); //2回目の呼び出し方法での記述の仕方がわからない rewind( fp ); //3回目の呼び出し方法での記述の仕方がわからない fclose(fp); } ---yasa.txtの内容--- オレンジ ● みかん ● いちご × もも ● ぶどう × キウイ ●

  • C言語の自己参照型プログラムについて

    #include <stdio.h> #include <string.h> #include <stdlib.h> struct list { int key; /* キー */ char name[20]; /* 名前 */ struct list *next; /* 次のデータへのポインタ */ }; struct list *add_list(int key, char *name, struct list *head); void show_list(struct list *p); void free_list(struct list *p); int main(void) { struct list *head; /* 先頭ポインタ */ char name[20]; int key = 0; head = NULL; /* 先頭ポインタにNULLを設定 */ printf("キーと名前(MAX:19文字)を入力(終了:CTRL+Z)\n"); while (scanf("%d %s", &key, name) != EOF) { /* リストにデータを登録 */ head = add_list(key, name, head); } /* リストの表示 */ show_list(head); /* リストの開放 */ free_list(head); return 0; } /*** リストにデータを登録 ***/ struct list *add_list(int key, char *name, struct list *head) { struct list *p; /* 記憶領域の確保 */ if ((p = (struct list *) malloc(sizeof(struct list))) == NULL) { printf("malloc error\n"); exit(EXIT_FAILURE); } /* リストにデータを登録 */ p->key = key; strcpy(p->name, name); /* ポインタのつなぎ換え */ p->next = head; /* 今までの先頭ポインタを次ポインタに */ head = p; /* 新たな領域を先頭ポインタに */ return head; } /*** リストの表示 ***/ void show_list(struct list *p) { while (p != NULL) { /* 次ポインタがNULLまで処理 */ printf("%3d %s\n", p->key, p->name); p = p->next; } } /*** リストの開放 ***/ void free_list(struct list *p) { struct list *p2; while (p != NULL) { /* 次ポインタがNULLまで処理 */ p2 = p->next; free(p); p = p2; } } これを実行すると、 新しく入力された順にリストが表示されます。 そうではなく、キーの昇順に表示したいです。 どなたかそのように実行できるようにプログラムを書き換えてくれませんか? 図々しいですがよろしくお願いいたします。m(_ _)m

専門家に質問してみよう