• ベストアンサー

ファイルから読み込んだデータを構造体に格納できますか?

1レコード19バイトのファイルを 読み込む処理を行っています。 地区名10バイト 県名8バイト 改行1バイト このデータをdouken(構造体)に格納したいのですが >while (fgets(dou,19,fp) != NULL){ で、エラーになってしまいます。 どのようにしたら ファイルから読み込んだデータを 構造体に格納できますか? #include<stdio.h> #include <stdlib.h> struct douken { char tiku[10]; char ken[8]; } main(void){ FILE *fp; struct douken dou[100]; int i; fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } while (fgets(dou,19,fp) != NULL){ ・ ・ ・

  • niiza
  • お礼率43% (211/486)

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

  • ベストアンサー
回答No.5

>>while (fgets(buffer,20,fp) != NULL){ >と、するということですか? >その場合、 >ここのサイズは必ず4の倍数になるということですよね? 構造体を直接扱うと、アーキテクスチャやコンパイラ依存してしまいます。 32bit機なら4byteですし、16bit機なら2byte。64bit機なら8byteです。 また、コンパイラの設定によってもどのように確保されるかまったく分からないのです。 一度バッファに蓄えてからmemcpyでコピーする方が安全ですし、可搬性があります。 C言語では\0を文字列の終端文字として使用しているので、10文字格納したいなら11byte確保する必要もあります。 簡単に修正してみました。 #include <stdio.h> #include <stdlib.h> #include <memory.h> typedef struct douken_ { char tiku[11]; char ken[9]; } douken; int main(void){ FILE *fp; douken dou [100]; char buff [18 /* douken */ + 1 /* LF(\n) */ + 1 /* \0 */]; int i; i = 0; fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } // douを\0で埋める memset (dou , '\0' , sizeof dou); // 一度バッファに格納 while (fgets(buff,sizeof buff,fp) != NULL){ // memcpy関数でコピー memcpy(&dou[i],buff,10); memcpy(&dou[i],buff+10,8); // 構造体配列より大きなファイルを開いたときの配慮 if (i == 99) break; i++; } return 0; }

niiza
質問者

補足

ご返事有り難うございました。 参考のプログラムまで書いて頂いたので とても勉強になりました。 参考のプログラムで 幾つか質問があるのですが… 1. >typedef struct douken_ { >char tiku[11]; >char ken[9]; >} douken; どうして「typedef」というのを 入れたのかが分かりません。 本を読むと 構造体の場合は省略することが出来ると 書かれてあったのですが…。 どのような利点があるか 教えて下さい。 2. // douを\0で埋める memset (dou , '\0' , sizeof dou); どのような理由で douを\0で埋めるんですか? 3. 確認をするために 一番最後のところでprintfを書いてみました。 >if (i == 99) break; >i++; printf("%s",dou[i]); と、したところ 「nullnullnull・・・」 となりました。 printf("%s",dou[i].tiku); としたところ 何も表示されませんでした。 ファイルの中身は漢字なんですが そこが問題なのでしょうか? それとも別の原因があるのでしょうか? 面倒をお掛けしますが よろしくお願いします。

その他の回答 (8)

  • R32C
  • ベストアンサー率39% (115/290)
回答No.9

#7です -------------------------------------- douP = dou; while ((fgets((char*)douP++,sizeof(struct douken),fp)) != NULL) {} --------------------------- i=0; while ((fgets((char*)dou[i++],sizeof(struct douken),fp)) != NULL) {} --------------------------- でも、同じです。ポインタか配列かの違いだけです。 コンパイラの性能等にもよりますが、上記のポインタを使ったほうが 若干早いか、コードが小さくなる場合が多いです。

niiza
質問者

お礼

ご返事有り難うございました。 大変に参考になりました。

回答No.8

構造体を fgets で読もうとしてるのがたぶん変。 (構造体のサイズは、sizeof で分かるんだけど。) そもそもファイルはテキストでしょうかバイナリでしょうか。テキストなら、構造体の要素 tiku や ken をそれぞれ読んでそれを構造体に入れるといいのでは。

niiza
質問者

補足

ご返事が遅れましてすいません。 お陰様で随分と理解を深めることが出来ました。 >そもそもファイルはテキストでしょうかバイナリでしょうか。 テキストです。 >テキストなら、構造体の要素 tiku や ken をそれぞれ読んで >それを構造体に入れるといいのでは。 ということは、 shirousa01さんが回答して頂いたように >while (fgets(buff,sizeof buff,fp) != NULL){ と、いったんバッファに蓄えて >memcpy(&dou[i].tiku ,buff,10); >memcpy(&dou[i].ken ,buff+10,8); と、入れればよいと言うことでしょうか? ご面倒かとは思いますが ご教授して頂けたら幸いです。

  • R32C
  • ベストアンサー率39% (115/290)
回答No.7

[admin@opteron99] ~/gcctext $ less ex3.fil 12345abcdefgh^M一二三四五ABCD^M1234567890IJKLMNOP [admin@opteron99] ~/gcctext $ cat test5.c #include<stdio.h> #include <stdlib.h> #define NofLine 3 #define SizeofLineEnd 1 #if MSVCC #pragma pack(push,1) struct douken { char tiku[10]; char ken[8]; char crlfNULL[SizeofLineEnd+1]; } ; #pragma pack(pop) #endif #if GNUGCC struct douken { char tiku[10]; char ken[8]; char crlfNull[SizeofLineEnd+1]; } __attribute__((packed)); #endif int main(void){ FILE *fp; int i; struct douken dou[NofLine]; struct douken *douP; printf("struct douken SIZE = %d\n",sizeof(struct douken)); printf("dou SIZE = %d\n",sizeof(dou)); fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } douP = dou; while ((fgets((char*)douP++,sizeof(struct douken),fp)) != NULL) {} douP = dou; for(i=0;i<NofLine;i++) { printf("Line%d:=",i+1); printf("tiku:%10.10s:",douP->tiku); printf("ken:%8.8s\n",douP->ken); douP++; } printf("end\n"); exit(0); } [admin@opteron99] ~/gcctext $ cc -DGNUGCC -g -Wall test5.c [admin@opteron99] ~/gcctext $ ./a.exe struct douken SIZE = 20 dou SIZE = 60 Line1:=tiku:12345:ken:abcdefgh Line2:=tiku:一二三四五:ken:ABCD Line3:=tiku:1234567890:ken:IJKLMNOP end [admin@opteron99] ~/gcctext $ ----------------------------------------------------------------------------- Cygwin ShitJIS 改行文字は、CRのみとしています。 直接構造体にとる方法は、独自プロトコルのデータのやり取り等で 比較的よく使われると思っています。(使っていました。) CPUやコンパイラの仕様によりアライメントに注意は必要ですが、 きっちりコンパイラに指定すれば、できないなんてことはないでしょう。 指摘事項について、ご確認されていないようですので回答しますと fgetsは、第2引数sizeよりも1バイト少ないデータをストリーム から読んで、第1引数のアドレスに書く、ただし、EOFまたは改行で 終わる。最後にNULLを書く。 ということなので、fgetsのwhileで取得するには、 tikuが10バイト、kenの8バイト、改行1文字(貴殿の指定により1文字としました。 Windowsなら2バイトですね)、NULL1バイトの計20バイトの領域が必要になります。 ですので、18を指定していたことと、領域の定義が不足していたことが貴殿のプログラム の問題のポイントだと思います。また他にもdouを100個の配列にしていますが まったくケアされていないこともバグのひとつですね。 上記プログラムもその2点とキャストをいれたぐらいです。 それからアライメントの指定を追加しているだけです。 それから、 改行およびNULLは飛ばして構造体に入れたいのであれば、fgetsでは20バイトのバッファ に取得し、18バイトを構造体にコピーするほうが、無駄なメモリを取らないので いい方法ですね。 その場合は、doukenから、crlfNullのメンバーを削除し、buffを定義(20byte)、 データ取得の部分を以下に置き換えるといいでしょう。 while ((fgets(buff,sizeof(buff),fp)) != NULL) { memcpy(douP++,buff,sizeof(struct douken)); }

niiza
質問者

補足

ご返事が遅れましてすいません。 折角回答して頂いたので なんとか理解しようと頑張ってみましたが 初心者の私には難しかったです。 ごめんなさい。 早くこのプログラムが理解できるように 勉強していきたいと思います。 一つだけ質問させて頂きたいのですが…。 >struct douken dou[NofLine]; >struct douken *douP; 普通に宣言した後に ポインタで宣言していますよね。 これはどのような意味があるんですか? ご面倒かとは思いますが ご教授して頂けたら幸いです。

回答No.6

1.どのような利点があるか 構造体を定義すると struct douken型 という型が定義されますが、好みの問題ですがstructを何度も書くのは面倒な為、構造体の名前を struct douken_型 として、それをtypedefで douken型 と再定義しています。 この定義の仕方はよく使われている方法です。 2.douを\0で埋めるんですか? 宣言しただけでは、構造体の中にゴミが詰まっています。 普段は意識しなくても問題ありませんが、ファイルを扱う場合や、構造体の場合、そのデータがバグにつながる可能性があるため、\0で初期化した方がバグが発生しにくいので、\0で初期化しています。 3.確認したところ、いくつか間違いがありました。 char buff [18 /* douken */ + 2 /* CrLf(\n\r) */ + 1 /* \0 */]; memset (dou , '\0' , sizeof dou); memset (buff, '\0' , sizeof buff); while (fgets(buff,sizeof buff,fp) != NULL){ memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,8); if (i == 99) break; i++; memset (buff, '\0' , sizeof buff); } データは漢字でも問題ありませんが、1文字2バイトになります。 また、encodingの問題がある場合もあります。 私がテストしたところ問題なく動作しました。

niiza
質問者

補足

ご返事が遅れましてすいません。 お陰様で随分と理解を深めることが出来ました。 幾つかご確認と質問があるのですが…。 >char buff [18 /* douken */ + 2 /* CrLf(\n\r) */ + 1 /* \0 */]; 18というのはtikuとkenを合わせたバイト数 +2というのはtikuとkenを合わせた改行文字数 +1というのは終端データ を確保していると考えて 宜しいのでしょうか? >memset (dou , '\0' , sizeof dou); というのは douのバイト数分 0を埋めていると言うことでしょうか? >memcpy(&dou[i].tiku ,buff,10); ポインタにされていますよね? 実数(この言い方が正しいのか分かりませんが…) でも、出力できました。 どうしてポインタにされたのでしょうか ご面倒かとは思いますが ご教授して頂けたら幸いです。

  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.4

> 32bit機というのは、どういうことですか? 現在主流のPCのことです。 >> tiku:4バイト + 4バイト + 2バイト + 2バイト(ゴミ) > どうして地区10バイトが > このようになるのでしょうか? データを収納する「箱」が4バイトの大きさだから、です。 tikuに"1234567890"というデータが入っているとすると 実際には [1234][5678][90??] という4*3=12バイトの領域を使うことになります。 ??の部分が「ゴミ」です。

niiza
質問者

補足

ご返事有り難うございました。 お陰様で良く理解することが出来ました。 >while (fgets(buffer,20,fp) != NULL){ と、するということですか? その場合、 ここのサイズは必ず4の倍数になるということですよね?

回答No.3

構造体ポインタをキャラクタポインタに型キャストすれば可能かとおもいますが、構造体を直接ファイルから扱うのはバグにつながりますよ? まず、おそらく上記の構造体のサイズは18バイトにならない可能性が高いです。 32bit機の場合、4バイト単位で数値を扱う為 tiku:4バイト + 4バイト + 2バイト + 2バイト(ゴミ) ken:4バイト + 4バイト の20バイトになっていると思います。

niiza
質問者

補足

ご返事有り難うございました。 少し質問があるのですが…。 >32bit機の場合、4バイト単位で数値を扱う為 32bit機というのは、どういうことですか? >tiku:4バイト + 4バイト + 2バイト + 2バイト(ゴミ) どうして地区10バイトが このようになるのでしょうか? 初歩的な質問かも知れませんが ご教授して頂けたら幸いです。

  • R32C
  • ベストアンサー率39% (115/290)
回答No.2

fgetsの仕様をよく確認ください。18+(改行文字数)1+(\0の終端データ)1要求する必要があると思います。 デバッガにたよるのもあまりよくありませんが、デバッグされてはいかがでしょうか? 以下、そのままgdbを動作させた場合のログの一部です。 (gdb) run Breakpoint 1, main () at test4.c:24 (gdb) p dou $1 = {{tiku = "1234567890", ken = "abcdefgh"}, {tiku = "\000G, ken = "<\000\000\000\004\000\000"}, {tiku = "\004\000\000\000P, ken = "\021\000}, {tiku = ", {tiku = "\000\000, ken = "Uy (gdb) next (gdb) next Breakpoint 1, main () at test4.c:24 (gdb) p dou $2 = {{tiku = "\n\00034567890", ken = "abcdefgh"}, {tiku = "\000G, ken = "<\000\000\000\004\000\000"}, {tiku = "\004\000\000\000P, ken = "\000\000 (gdb) ex3.filは 234567890abcdefgh 1234567890ABCDEFGH 1234567890IJKLMNOP にしています。 環境は、linux で、gcc4.1.1です。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

fgets の使い方を見れば「どうしてエラーになるのか」はほとんど明らかだと思うんだけど, 1.fgets は第1引数に char * を要求するけど struct douken * は char * に変換できない というのが原因だよね. ただ, これは「コンパイラが文句を言ってくれる*たちのよい*エラー」であって, 実際には 2.struct douken は 18バイトかもしれないけど fgets で 19バイト読み込んでいる という「コンパイラがきっと文句を言わない*質の悪い*エラー」もまぎれこんでいるので注意.

niiza
質問者

補足

ご返事有り難うございました。 少し質問があるのですが…。 >1.fgets は第1引数に char * を要求するけど > struct douken * は char * に変換できない ということは、 このようにしていったんchar型に格納しないと いけないということですか? char buffer[19]; while (fgets(buffer,19,fp) != NULL){ >2.struct douken は 18バイトかもしれないけど fgets で >19バイト読み込んでいる 地区名10バイト 県名8バイト 改行1バイト というレコードフォーマットでしたので 19バイトと指定したのですが 18バイトということは 改行は含まないで指定すると言うことですか? ご教授して頂けたら幸いです。

関連するQ&A

  • if文で…

    いつもお世話になっております。 ------------------------ typedef struct douken_ { char tiku[11]; char ken[9]; } douken; int main(void){ FILE *fp; douken dou [100]; char buff [18 /* douken */ + 2 /* CrLf(\n\r) */ + 1 /* \0 */]; int i; i = 0; fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } memset (dou , '\0' , sizeof dou); memset (buff, '\0' , sizeof buff); 問題はここから----------------- while (fgets(buff,sizeof buff,fp) != NULL){ memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,10); if (&dou[i].tiku == &dou[i-1].tiku){ printf("%s %s",&dou[i-1].tiku,&dou[i].tiku,&dou[i].ken);} else{ printf("-----------------------"); } ------------------------ 上記のプログラムでは ファイルから読み込んだデータを 構造体に格納して if文で現データと全データを 比較するという処理をしています。(つもり) 構造体に格納するところまでは 出来たのですが if文のところが上手く行きません。 例えば 現データ(tiku)関東地区 前データ(tiku)関東地区 と、同じ場合は 関東地区 東京 と、表示したいのに ----------- と、elseの処理をしてしまいます。 対処方法をご存じでしたら、 ご教授して頂けたら幸いです。

  • ポインターについて

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=2352832 で、質問させて頂いた者です。 ポインターの使い方について 理解できないところがありましたので 新しく質問をさせて頂きました。 ----------- ↓構造体の型を宣言しています typedef struct douken_ { char tiku[11]; char ken[9]; } douken; int main(void){ FILE *fp; ↓変数を宣言 douken dou [100]; ・ ・ ・ while (fgets(buff,sizeof buff,fp) != NULL){ ファイルから読み込んだデータを構造体に格納 memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,10); 【ここが問題】 現データと全データを比較する if (strcmp(dou[i].tiku , dou[i-1].tiku)){ ----------- if文で現データと全データを比較する時に、 実数だと正常に動くのですが ポインターで指定すると 警告が出てしまいます。 if (strcmp(&dou[i].tiku , &dou[i-1].tiku)){ とすると >警告 W8075 kadai3-2.c 33: 問題のあるポインタの変換(関数 main ) という警告が出てしまうのです。 どうしてポインターで指定すると 警告が出るのかが分からないのです。 (memcpyではファイルから読み込んだデータを 構造体に格納するときはポインターで指定しているのに…) ご教授して頂けたら幸いです。

  • csvファイルを構造体に格納したいです

    ファイル内容 ******************** あいう,,さしす たちつ,なにぬ,はひふ まみむ,, あいう,win, ******************** #include <stdio.h> #include <string.h> #define MBF 256 struct tb{ char aaa[32]; char bbb[32]; char ccc[32]; }; int main(){ struct tb tbl[20]; struct tb *tp; int ntb,itb; FILE* fi; FILE* fo; char buff[MBF]; // 入力 fi = fopen("sample.csv","r"); // 検査省略 if( fi == NULL ){ printf( "%sファイルが開けません\n" ); return -1; } ntb = 0; while ( fgets(buff,MBF,fi ) != NULL ) { strcpy(tbl[ntb].aaa,strtok(buff,",")); strcpy(tbl[ntb].bbb,strtok(NULL,",")); strcpy(tbl[ntb].ccc,strtok(NULL,",")); ntb++; } fclose( fi ); // 出力 fo = fopen("csvo.csv","w"); if( fo == NULL ){ printf( "%sファイルが開けません\n" ); return -1; } for ( itb=0;itb<ntb;itb++ ) { tp = tbl+itb; fprintf(fo,"%s%s%s",tp->aaa,tp->bbb,tp->ccc); } fclose( fo ); return 0; } csvファイルないようが以下であれば格納できるけど、すごく困ってます。 ******************** あいう,かきく,さしす たちつ,なにぬ,はひふ まみむ,やゆよ,らりる ********************

  • csvファイルを構造体に格納したいです

    ファイル内容 ******************** あいう,,さしす たちつ,なにぬ,はひふ まみむ,, あいう,win, ******************** #include <stdio.h> #include <string.h> #define MBF 256 struct tb{ char aaa[32]; char bbb[32]; char ccc[32]; }; int main(){ struct tb tbl[20]; struct tb *tp; int ntb,itb; FILE* fi; FILE* fo; char buff[MBF]; // 入力 fi = fopen("sample.csv","r"); // 検査省略 if( fi == NULL ){ printf( "%sファイルが開けません\n" ); return -1; } ntb = 0; while ( fgets(buff,MBF,fi ) != NULL ) { strcpy(tbl[ntb].aaa,strtok(buff,",")); strcpy(tbl[ntb].bbb,strtok(NULL,",")); strcpy(tbl[ntb].ccc,strtok(NULL,",")); ntb++; } fclose( fi ); // 出力 fo = fopen("csvo.csv","w"); if( fo == NULL ){ printf( "%sファイルが開けません\n" ); return -1; } for ( itb=0;itb<ntb;itb++ ) { tp = tbl+itb; fprintf(fo,"%s%s%s",tp->aaa,tp->bbb,tp->ccc); } fclose( fo ); return 0; } csvファイルないようが以下であれば格納できるけど、すごく困ってます。 ******************** あいう,かきく,さしす たちつ,なにぬ,はひふ まみむ,やゆよ,らりる ********************

  • ファイルから読みこんで構造体に格納する、

    shohinというファイルに RX-100 odango_tsumeawase 3000という のが 五行ならんでいるのですが、 これを読み込んで struct shohin{ char code[10]: char name[40]; int price; } にファイルから読みこんで構造体配列に 格納したいのですが、構造体配列に格納する やりかたがわかりません。 構造体配列は struct shohin list[];というのを宣言しています。 ファイルから一行読み込んで fprintf()を使おうと思うのですが、 それはできますか? メンバ毎に格納したいのですが、 それがわかりません お願いします。

  • 構造体と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の内容--- オレンジ ● みかん ● いちご × もも ● ぶどう × キウイ ●

  • CSVファイルの内容を構造体に格納したい(Unix使用)。

    こんにちは。私は30代の男性です。 「名前」「身長」「体重」が記載されたCSVファイルの内容を読み取って、構造体の「name」「height」「weight」に格納するプログラムを作っています。CSVの内容は A,175,80 B,167,89 C,155,45 ・ ・ ・ Z,188,70 だと仮定します。数値が読み取れているか、下記のように「tp = strtok(file_image, ",\n" );」の前後に「printf("%s\n", file_image);」を置いてみたら、strtok前では全て表示されるのに、strtok後では「ABC」しか表示されません。これでは全てのデータを構造体に格納できないので、困っています。 1.どのようにすれば、数字も取り出せる(読み取れる)でしょうか? 2.効率よく構造体に格納するには、どのようにしたらよいでしょうか? アドバイスを頂ければ幸いです。宜しくお願いいたします。 #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <string.h> int main(int argc, char *argv[]) { FILE *fp = NULL; int rtn = 0; if ((fp = fopen(argv[1], "r")) == NULL) { printf("ファイルオープンに失敗しました。\n"); return 1; } if (argc != 2) { printf("ERROR: オプションの数に過不足があります。\n"); return 1; } rtn = change_csv(fp); return 0; } int change_csv(FILE *fp) { int i; int j; char file_image[256]; /* 読み込んだ先のメモリの領域 */ char *tp; for (i = 0; i <= 256; i++) { if (fgets(file_image, 256, fp) == NULL) { if (ferror(fp) != 0) { printf("ERROR: 読み込みに失敗しました。\n"); return 1; } } if (feof(fp) != 0) { break; } printf("%s\n", file_image); tp = strtok(file_image, ",\n" ); printf("%s\n", file_image); } fclose(fp); return 0; }

  • ファイルから構造体へデータを格納(動的メモリ割り当て)

    C言語の勉強をしいております。 typedef struct address { char names[32]; /* 名前 */ char tels[32]; /* 電話番号 */ struct address *prev; /* 前のリスト */ struct address *next; /* 次のリスト */ }Address; という構造体へ、ファイルから読み込んだテキストデータ(名前と電話番号がTABで区切られている)を格納したいのですが、配列ではなく、動的にメモリを確保しながら格納する方法を教えていただけないでしょうか? 処理の流れとしては、 ・1つめの構造体の*prevにはnullを入れておく。 ・1つめの構造体へファイルの1件目のデータを格納する。 ・ファイルのデータがまだある場合には、malloc関数を使ってメモリを確保し、malloc関数からの戻り値を1つめの構造体の*nextへ格納する。 ・構造体へ2件目のデータを格納する。 このような感じだろうという程度しか分からず、ソースも書けずにいます・・・。 配列を使用したサンプルはあるんですが、動的に処理を行う方法を教えていただけないでしょうか? よろしくお願いいたします。

  • csvファイルのデータを構造体に

    csvファイルのカンマを数えて任意の文字列を抜き出すまでは出来たのですがそこから構造体に格納するまでがこちらのサイトでも検索しましたがよくわかりません。 ご指摘のほどよろしくお願いします。 csvデータ 番号,名前,住所,電話,年齢,性別 1,佐藤,東京,1234,33,A 2,田中,,5678,22, 3,坂井,名古屋,,,B ・ ・ 番号,住所,電話,年齢を格納する場合 struct k_data { char no[4];/* 出来れば番号を右詰めにしたい */ char add[20]; int tel; int age; } kaiin[256]; /* 文字列を抜き出す↓ */ int main(void) { FILE *fp1,*fp2; char dat[256]; char *ch; int cnt; /* fp1 ファイルオープン */ /* fp2 ファイルクローズ */ while (fgets(dat, 256, fp1) != NULL) { cnt = 0; for (ch = dat; *ch != '\0'; ch++) { if (*ch ==',') { if (cnt == 0) { putc(*ch, fp2); } if (cnt == 2) { putc(*ch, fp2); } if (cnt == 3) { putc(*ch, fp2); } if (cnt == 4) { putc('\n', fp2); } cnt++; } else { if (cnt == 0) { putc(*ch, fp2); } if (cnt == 2) { putc(*ch, fp2); } if (cnt == 3) { putc(*ch, fp2); } if (cnt == 4) { putc(*ch, fp2); } } } putc('\0', fp2); } fclose(fp2); fclose(fp1); }

  • CSVファイルを読み込み構造体のメンバ、"value"に格納し、その後

    CSVファイルを読み込み構造体のメンバ、"value"に格納し、その後平均値を求めて構造体のメンバ、"ave"に格納し表示させたいのですが、読み込み格納している最中で、セグメンテーション違反で終了してしまいます。どなたかよろしければ教えて頂けないでしょうか。 プログラム ************************************************** #include <stdio.h> #include <string.h> #include <stdlib.h> #define SIZE 64 #define FILE_NAME_00 "f_00_01.CSV" struct Data{ double value; double ave; }; int main(int argc, char *argv[]) { FILE* fp,*fo; // ファイルポインタ用 int n, i, file_size; struct Data *dat; if ((fp = fopen(FILE_NAME_00,"r")) == NULL) { printf( "file open error\n" ); exit(EXIT_FAILURE); } fseek(fp, 0, SEEK_END); file_size = ftell(fp); dat = (struct Data*)malloc(file_size); printf("malloc address= %p, file size= %d\n", dat, file_size); fseek(fp, 0, SEEK_SET); i = 0; for(i=0;i<file_size;i++){ fscanf(fp,"%lf",&dat[i].value); printf("%lf\n",dat[i].value); i++; } fclose(fp); printf("\n"); free(dat); return 0; } *************************************************** f_00_01.CSV *************************************************** 2.313725 2.312810 2.314031 2.316167 2.315557 2.313725 . . . . . ***********************************************

専門家に質問してみよう