• ベストアンサー

ファイルの入出力に関する質問

CSVファイルを読み込んで、処理をするプログラムを書いています。 しかし、うまくいきません。 CSVファイルは 単語1,数値データ 単語2,数値データ のようになっており、 これをsの配列に格納したいと思っています。 プログラムは以下の通りなんですが。。。 strtokはhttp://www9.plala.or.jp/sgwr-t/lib/strtok.html を参考にしました。 どなたかおしえていただけないでしょうか? #include<stdio.h> #include <string.h> int main(void) { FILE *fp; char s[1000][1000]; char tp[256]; int i=0; if((fp=fopen("in.csv","r"))==NULL){ printf("ファイルオープンできませんよ\n"); exit(1); } while(fgets(tp,256,fp)!=NULL){ tp=strtok(fp,","); puts(s[i][0]=tp); while (tp != NULL ) { tp = strtok(NULL,","); if (tp= NULL ){ puts(s[i][1]=tp); }}i++; } return(0); }

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

  • ベストアンサー
  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.1

> char s[1000][1000]; 1000(行)x2(データレコード数)x256(文字列長)の3次元配列が必要です。 char s[1000][2][256]; #tpが256なのでそれ以上のサイズは不要 > while(fgets(tp,256,fp)!=NULL){ iが1000になった時点(1000行読んだ)でもループアウトするようにしないとエラーになります。 > tp=strtok(fp,","); > tp = strtok(NULL,","); 上のstrtok()の第1引数はfpではなくtpです。 また戻り値はポインタ変数を別に用意して受け取りましょう。 > puts(s[i][0]=tp); > puts(s[i][1]=tp); このように文字列をコピーすることはできません。 strcpy()を使いましょう。 strcpy(s[i][0], tp); puts(s[i][0]); なおfscanf()を使った方が楽かもしれません。

ionwide
質問者

補足

自分なりに考えたのですが、うまく動きません。 int main(void) { FILE *fp; char s[5][1000][2][256]; char tp[256]; char *ttp; int i=0,ii=0; if((fp=fopen("out1.csv","r"))==NULL){ printf("ファイルオープンできませんよ\n"); exit(1); } while(fgets(tp,256,fp)!=NULL){ ttp=strtok(tp,","); strcpy(s[0][ii][i][0],ttp);//ここにエラーがでます。 puts(s[0][ii][i][0]);//ここにエラーがでます。 while (ttp != NULL ) { i++; ttp = strtok(NULL,","); if (ttp= NULL ){ strcpy(s[0][ii][i][0],ttp);//ここにエラーがでます。 puts(s[0][ii][i][0]);//ここにエラーがでます。 }}i=0; ii++;if(ii>=1000)break; } return(0); } //ここにエラーがでます。 というところにエラーがでます。 もしよければアドバイスをいただけないでしょうか?

その他の回答 (1)

  • yukimican
  • ベストアンサー率70% (112/159)
回答No.2

CSVファイル ・タイトル行なし ・最大1000行まで ・1行に2項目のデータ  - カラム1=単語(文字列/最大256文字)  - カラム2=数値データ(整数) 動作仕様 ・CSVファイルを開き、一行ずつ読み込む ・データを項目別に分け、すべてメモリ上の変数に設定する とみなして、勝手に書いていきます。 1.格納先について   構造体 または 項目別の変数 で配列を作る必要があります。   [例1]    char key[256][1000];    int val[1000];   [例2]    struct dat_{     char key[256];     int val;    } dat[1000]; 2.行の読み込みについて   CSVであれば、strtokを使うよりも、   1) 文字列の先頭からstrchr()でカンマ文字を探し、   2) 文字列先頭からカンマ文字の手前まで(単語の部分)を    strncpy()で文字列用の変数に格納し、   3) カンマ文字の後ろから、行の終端まで(数値の部分)を    atoi()で文字列から数値に変換   という手順で各行を処理していくのが良いと思います。   [擬似コード]   ※処理の流れを書くだけで、動作保証はしません。   char line[256]; // 行   char *camma; // カンマ文字の位置   int *key_len // 単語の長さ   int i=0;   while(fgets(fp,256,line)!=NULL){ //行読み込み    camma = strchr(line, ','); // カンマ文字を検索    if(camma) {     word_len = camma - line; // 文字数計算     strncpy(dat[i].key, line, key_len); // コピー     str[key_len] = '\0'; // 末尾に注意     dat[i].val = atoi(camma+1); // 数字 → 数値     if(++i >= 1000) break; // 1000行までなので。    }   }

ionwide
質問者

お礼

ご回答ありがとうございます。 参考にさせていただきます。 しかし、自分の書いたプログラムでも動かせるように努力したいと 思います。

関連するQ&A

  • エラーがないのに正常に動かない

    以前質問したのものです。 アドバイス等いただき、プログラムを修正しエラーをなくしました。 しかし、プログラムが動きません。。。 プログラムの動作は CSVファイルを読み込んで、処理をする。 CSVファイルは 単語1,数値データ 単語2,数値データ のようになっており、 これをsの配列に格納したいと思っています。 プログラムの内容は #include<stdio.h> #include <string.h> int main(void) { FILE *fp; char s[5][1000][2][256]; char tp[256]; char *ttp; int i=0,ii=0; if((fp=fopen("out1.csv","r"))==NULL){ printf("ファイルオープンできませんよ\n"); return -1; } while(fgets(tp,256,fp)!=NULL){ ttp=strtok(tp,","); strcpy(&s[0][ii][i][0],ttp); puts(&s[0][ii][i][0]); while (ttp != NULL ) { i++; ttp=strtok(NULL,","); if (ttp != NULL ){ strcpy(&s[0][ii][i][0],ttp); puts(&s[0][ii][i][0]); }}i=0; ii++;if(ii>=1000)break; } return(0); } です。 わけがわからなくなりました(泣 どこが原因なのかも書いていただけるとありがたいです。

  • C言語 strtok

    失礼します。現在こちらでアドバイスを頂きfgetcを使用して配列に格納をすることができたのですが、CSVをカンマ区切りで格納したいのですが上手くいかず困っています。strtokを使用方法をドキュメントを読んでもうまく区切ったものを配列に入れる方法がわかりません 何卒よろしくお願いします。 ソースコード #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include<string.h> #define MAXITEM 1400 int split(char *str, const char *delim, char *outlist[]) { char *tk; int cnt = 0; tk = strtok(str, delim); while (tk != NULL && cnt < MAXITEM) { outlist[cnt++] = tk; tk = strtok(NULL, delim); } return cnt; } int main(void) { FILE *fp; char *fname = "testfile.csv"; char *tp; char *array[1400]; char *test[11][1400]; char c; int i = 0; int n,y; char *tp[1400]; fp = fopen(fname, "r"); if (fp == NULL) { printf("%sファイルが開けません¥n", fname); return -1; } while ((c = fgetc(fp)) != EOF) { array[i] = (char)c; i++; } tp = strtok(array, ","); puts(*tp); while (tp != NULL) { tp = strtok(NULL, ","); if (tp != NULL)puts(tp); } for (n = 0; n < 11; n++) { for (y = 0; y < 1400; y++) { test[n][y] = tp[y]; printf("%c", test[n][y]); } } fclose(fp); return 0; }

  • C言語でファイルの内容を strtok関数 を使って数字と文字を分けて

    C言語でファイルの内容を strtok関数 を使って数字と文字を分けて配列に格納したいのですが、うまくできません。 どこが駄目なのかご指摘をお願いします! ファイル内容 20 田中 10 鈴木 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc,char *argv[]) { FILE *fp; char str[256]; char *tp; int i=0; int num[10]; char na[10]; fp=fopen(argv[1],"r"); while(fgets(str,sizeof str,fp)!=NULL); tp = strtok ( str, " " ); while(tp != NULL ) { num[i]=atoi(tp); tp = strtok( NULL," "); if ( tp != NULL ){ na[i]=*tp; } i++; } printf("%d\n%s",num[0],na[0]); printf("%d\n%s",num[1],na[1]); fclose(fp); return 0; }

  • C言語で、ファイルを読み込んで数字と名前に分けて配列に格納に関する質問

    C言語で、ファイルを読み込んで数字と名前に分けて配列に格納に関する質問です! ファイルを開いた後でエラーとなるのですが、何が足りないのでしょうか? ファイル内容 20 田中 10 鈴木 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc,char *argv[]) { FILE *fp; char str[256]; char *tp; int k,i=0; int num[10]; char na[10][20]; fp=fopen(argv[1],"r"); if(fp==NULL){ printf("ファイルを開けません\n"); return 1; }else{ printf("開けた\n"); } while(fgets(str,sizeof str,fp)!=NULL){ tp=strtok(str," "); num[i]=atoi(tp); tp=strtok(NULL," "); strcpy(na[i],tp); i++; } printf("%d\n%s\n",num[0],na[0]); printf("%d\n%s\n",num[1],na[1]); fclose(fp); return 0; }

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

  • Borland C CSVファイル読み込み

    CSVファイルを読み込み、読み込んだ値で計算を行うプログラムを作っています。 ・環境はWindows VISTA UltimateでBorland C++ Compiler 5.5  ・CSVファイルのデータの形式は 1,4532 4,2131 6,4301 . . ・データ数は決まっていて今のところ全部で12個 そして以下のようにCSVの読み込みプログラムを試しに組んだ所、実行時エラーがでました。 #include <stdio.h> #include <stdlib.h> #include <string.h> void main(void) { int AN[11][1]; int i=0,j=0,c=0; char buff[1024], *tp; FILE *fp; /*配列初期化*/ for(i=0;i<11;i++) { for(j=0;j<2;j++) { AN[i][j]=0; } } fp=fopen("test1.csv","r"); if(fp==NULL) { /* オープン失敗 */ printf("ファイルがオープンできません\n"); exit(1); /* 強制終了 */ } while( fgets(buff, 1024 , fp) != NULL ) { tp=strtok(buff , ","); if (tp !=NULL) {AN[i][j] = atoi(tp);} printf("%d\n",AN[i][j]); tp = strtok(NULL , ","); if (tp !=NULL) {AN[i][j+1] = atoi(tp);} printf("%d\n",AN[i][j+1]); i++; } fclose(fp); } 実行するとファイルクローズの後、問題が発生したためプログラムを終了しましたと出ます。"AN[i][j]=atoi(tp)"の配列部分を単純に変数にするとこのようなエラーは出ないのですが。 なぜエラーが出るのか、どなたかご教授願います。

  • 複数のファイルへの一括処理(困ってます)

    あるディレクトリ内の全てのファイルに同じ処理(添付のプログラムによるtest1.csvファイルに対する処理と同一の処理)をしたいと考えています。 どのようなプログラムを組めば良いのですか? 手法については検討もつかない状況です。 教えていただけないでしょうか? よろしくお願いいたします。 (1)添付のプログラム #include <stdio.h> #include <conio.h> #include <string.h> #include <stdlib.h> int main () { FILE *fp; char a[50]; double b; char *p; if((fp = fopen("test1.csv", "r")) == NULL) return 0; while(fscanf(fp, "%s\n", &a) != EOF){ p = strtok( a, "," ); b = atof(a); printf("%lf ", b); while(p != NULL) { p=strtok(NULL, ","); if(p != NULL) { b = atof(p); printf("%lf\n", b); } getch(); } } fclose(fp); return 0; } (2)プログラムで使うCSVファイル -749.95,1.499894061 -749.9,2.371277071 -749.85,3.01070131 -749.8,-0.92298313 -749.75,3.111961134 -749.7,-1.642278763 -749.65,2.759562723 -749.6,0.869387239 -749.55,1.400240703 -749.5,-0.574988131 -749.45,-2.282041367 -749.4,-1.104953718 -749.35,2.45568825 -749.3,-1.391859875 -749.25,-1.600438736 -749.2,0.116074589 -749.15,2.973864166 -749.1,2.652719198 -749.05,1.584699094 -749,2.129474673 -748.95,1.847275561 -748.9,2.974398019 -748.85,1.561458246 -748.8,2.897905731 -748.75,2.655075544 -748.7,-2.677451989 -748.65,-0.871814301 -748.6,-3.098832888 -748.55,2.565297638 -748.5,-2.073626148 -748.45,-0.300440285 -748.4,0.515248274 -748.35,2.983715685 -748.3,-2.47909508

  • ポインタについて

    途中までのソースコード typedef struct node{ char moji[128]; --------(1) }NODE; int main(int argc, char *argv[]){ FILE *fp; char buf[128]; NODE p[128]; char *tp; int i = 0; int j,k; int res; NODE temp; fp = fopen(argv[1],"r"); while(fscanf(fp,"%s",&buf) == 1){ tp = strtok(buf," ,.-"); strcpy(p[i].moji,tp); ---------(2) i++; while(tp != NULL){ tp = strtok(NULL," ,.-"); if(tp != NULL){ strcpy(p[i].moji, tp); --------(2) i++; } } } for(j = 0;j < i; j++) puts(p[j].moji); return 0; } file.txt これ以下の文字を読み込む -------------- The Java programming language is a general-purpose, concurrent, class-based, object-oriented language. It is designed to be simple enough that many programmers can achieve fluency in the language. 例えばこんなソースコードがあって、(1)をポインタにして、(2)のstrcpyを使わずにポインタだけで表現するとしたらどのようになるんですか?

  • strtokのしくみについて

    よろしくお願い致します。 strtokは以下のように使いますよね。 (と言っても今回初めて使うのですが) 1回目はstrを渡しているので自然ですが、2回目以降はNULLですよね。なのにどうしてstrを続けて分解するということが出来るのでしょうか? うまく説明できませんが、要はstrtokはどういうコードで実現されているのでしょうか? int main(void) { char str[] = "ABCD ef.1234.G"; char *tp; /* スペース.を区切りに文字列を抽出 */ tp = strtok( str, " ." ); puts( tp ); while ( tp != NULL ) { tp = strtok( NULL," ." ); if ( tp != NULL ) puts( tp ); } return 0; }

  • 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ファイルないようが以下であれば格納できるけど、すごく困ってます。 ******************** あいう,かきく,さしす たちつ,なにぬ,はひふ まみむ,やゆよ,らりる ********************