• ベストアンサー

C言語についてアドバイスをください。

CSVファイルの内容をfreadで読み込み、strtokを使わずにbuffに格納した後、 buffから1文字ずつbuff2へコピーさせていって、コンマがきたら数字、 改行がきたら名前と判別して、自作関数に渡して表示させたいです。 CSVファイルの内容は 『11,名前1(改行) 15,名前2(改行) 18,名前3』 といった感じです。 ------------------------------------------------------- #define _CRT_SECURE_NO_DEPRECATE 1 #include <stdio.h> #include <string.h> #include <stdlib.h> #define NUM 256 struct kou { short nenrei; char namae[30]; }; void pri(struct kou *o) { printf("%d\n%s\n",o->nenrei,o->namae); } int main(void) { FILE *fp; // ファイルポインタ char buff1[NUM] = {0}; char buff2[NUM] = {0}; char *fname = "text1.csv"; // ファイル名を指定 short i = 0; int n = 0; struct kou p; fp = fopen(fname, "r"); if(fp == NULL) { printf("%sファイルをオープンできませんでした。\n",fname); } fread(buff, 1, NUM, fp); while(buff1[n] != NULL) { buff2[n] = buff1[n]; // buff2[0]からbuff1の中を一文字ずつコピーしていく。 if(buff2[n] == ',') // buff2に格納されていく中にコンマがきたら以下の作業を行う。 { i = (short)atoi(buff2); // char型からshort型への変換 p.nenrei = i; } if(buff2[n] == '\n') { strcpy(p.namae,buff2); // p.namaeにbuff2をコピー。 pri(&p); } n++; } fclose(fp); printf("ファイルをクローズしました。\n"); return 0; } ------------------------------------------------------- 今のままだと 『11 11,名前1 11 11,名前1 15,名前2』 という表示になってしまいます。 while 内で既に読み込んだ部分を読み込ませないよう(表示させないよう)にできたら良いと思うんですが、そういったやり方はあるのでしょうか? むしろやり方を変えたほうが良いでしょうか・・・。 まだC言語を学び始めて日が浅いので、色々間違っている部分もあると思いますが、 そういったことを含めてアドバイスをいただけたらと思います。 よろしくお願いします。

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

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

以下の部分が要求仕様を満たしているのか確認しましょう int main(void) {   FILE *fp; // ファイルポインタ   char buff1[NUM] = {0};   char buff2[NUM] = {0};   char *fname = "text1.csv"; // ファイル名を指定   short i = 0;   int n = 0;   struct kou p;   fp = fopen(fname, "r");   if(fp == NULL)   {     printf("%sファイルをオープンできませんでした。\n",fname);   }   fread(buff, 1, NUM, fp);   // 読み込みが成功したのかチェックしなくてもいいのか   while(buff1[n] != NULL)   {     buff2[n] = buff1[n]; // buff2[0]からbuff1の中を一文字ずつコピーしていく。     if(buff2[n] == ',') // buff2に格納されていく中にコンマがきたら以下の作業を行う。     {       i = (short)atoi(buff2); // char型からshort型への変換       p.nenrei = i;       // カンマを処理したので次に取り込むbuf2への書き込み位置を       // 変更しなくてもいいのか     }     if(buff2[n] == '\n')     {       // buf2先頭から構造体のメンバーにコピーするのなら       // buf1/buf2にアクセスする変数nは1つで出来るのか       // この記述だと構造体のnameに"\n"が付加されるが       // これは意図した動作か       strcpy(p.namae,buff2); // p.namaeにbuff2をコピー。       pri(&p);     }     n++;   }   fclose(fp);   printf("ファイルをクローズしました。\n");   return 0; }

sounds24
質問者

お礼

丁寧な回答をありがとうございます。 しっかり読んで理解を深めようと思います。

その他の回答 (2)

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.3

#2です。 >pri(&p); pri関数の仕様から見て、ポインタを渡す必然性はないです。

sounds24
質問者

お礼

補足回答をありがとうございます。

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.2

>if(fp == NULL) ファイルが存在しない、などの理由でオープンできなかったときも 強引に読み込もうとしていますね。まずいです。 >fread(buff, 1, NUM, fp); 1行ずつ読み込むのでしたら、freadよりもfgetsあたりの方が使いやすいと思います。 ところで、buffという変数は定義していません。 >while(buff1[n] != NULL) NULLはポインタです。buff1[n]というchar型と比較することは正しくありません。 >i = (short)atoi(buff2); // char型からshort型への変換 >p.nenrei = i; iという中間的な変数を設ける必要はありません。 p.nenrei = atoi(buff2); でじゅうぶんです。 まずは、fgetsの使い方を調べてみてはいかがでしょうか。

sounds24
質問者

お礼

丁寧な回答をありがとうございます。 やっぱりか~という部分とそうなのか!という部分がありました。 しっかり読んで理解を深めようと思います。