- ベストアンサー
C言語 strtokでCSVをカンマ区切りで配列に格納する方法
- C言語のstrtok関数を使用して、CSVファイルをカンマ区切りで配列に格納する方法について困っています。
- 現在、fgetc関数を使用して配列に格納することはできましたが、CSVをカンマ区切りで格納する方法がうまく分かりません。
- strtok関数のドキュメントを読んでも、うまく区切ったデータを配列に入れる方法がわかりません。どなたか教えていただけますか?
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
>一体どこでiを回せばいいのか、今試しにwhileの下で回してみましたが違うみたですね、 なぜwhileの下なのでしょうか。 あてずっぽうではプログラムは完成しませんよ。 >iの値を0にするのは改行するときでしょうか? test[row][column][i] =(char)c; i++; ここでなにが行われるかが理解できていれば、答えは簡単なはずなのですが。 「文字」と「文字配列」と「文字列」の関係についておさらいしましょう。
その他の回答 (7)
- titokani
- ベストアンサー率19% (341/1726)
ヒントです。 >iの値を0にするのは改行するときでしょうか? 改行するときではなくて、改行を読み込んだときです。 そしてもう一か所、カンマを読み込んだ時です。 なおiを0にするだけでは、文字列の終端が書かれていないので、 test[row][column][i] = '\0'; も必要です。
- trapezium
- ベストアンサー率62% (276/442)
#2 ですが > test[row][column] = (char)c; は既に指摘されているので、 > 文字列用で三つになるんですね、、、、汗 三つになるというか、当初はファイル全体を > char array[1400]; に格納しようとしたのでは無いのですか? 実際のデータは可変サイズですから、通常は malloc() したりするとこですが。 そして `,' や `\n' の位置で `\0' ターミネートして、バッファへのポインタ (char *) を > char *test[11][1400]; の、行/列の位置に入れるものと思っていました。それにしては、11行、1400列と不自然な感じはしますが。 3次元配列化するのを止めはしませんが、ファイルサイズ以上にメモリを食うので非効率ではあります。上限を決め打ちするという制限もあります。
補足
お返事が遅くなりました、array[0][0] = xxxxのようにカンマ区切りでカウントアップしてarray[0][] = yyyyとなって改行でarray[1][0] = zzzzとなってほしかったです。 malloc() はまだしっかり調べていないので、みてきます。ありがとうございます。
- titokani
- ベストアンサー率19% (341/1726)
#1#3#4です。 あと、 while ((c = fgetc(fp)) != EOF) { こういった使いかたをする場合はcはintで宣言します。 char c; は、 int c; としてください。
- titokani
- ベストアンサー率19% (341/1726)
#1、#3です。 あと、fgetsとfgetcとを読み違えていることが多いようです。 話が全然違っていますので、きちんと読み分けるようにしましょう。
- titokani
- ベストアンサー率19% (341/1726)
#1です。 columnは列、rowは行ですので、配列に入れるなら必要ですよね。 で、 array[row][column] = (char)c; ここは違います。 test[row][column] = (char)c; これでも違います。 格納するのは文字列ですから、文字列に文字を追加する処理が必要です。 test[row][column][i] =(char)c; i++; という書き方になります。 当然、testの定義も char *test[11][1400]; このままではだめですので、 char test[11][1400][100]; といった定義になります。100の部分は適当に調整してください。 なお、iの値をどこかで0に戻す必要があります。どこで戻すべきかわかりますか?
補足
教えていただき有難うございます。周りに聞けるような人がいなくて、、文字列用で三つになるんですね、、、、汗 一体どこでiを回せばいいのか、今試しにwhileの下で回してみましたが違うみたですね、 iの値を0にするのは改行するときでしょうか?
- trapezium
- ベストアンサー率62% (276/442)
strtok() 使うなら fgets() や fread() でまとめて読み込んだ方が楽です。 fgetc() つかうなら `,' や `\n' を自前でチェックして、バッファに格納してやります。 > char *array[1400]; ここは明らかに char array[1400]; ただバッファとしては少すぎませんかね? それ以降もおかしいです。 > while ((c = fgetc(fp)) != EOF) { > array[i] = (char)c; > i++; > } ここでループを閉じてますがこれではダメで、fgetc() しながら `,' や `\n' が表われたら test[n][y] に、文字列 array の適切なポインタを格納します。
補足
ありがとうございます。 現在のコードではこういった形になりますが、カンマまでの文字列を格納したい場合fgetsのほうがいいのかもしれないです。確認します。 今のところのコードを記載させていただきます。 他の回答者の方に記載したコードはarrayをしようしていますがtestでした。すいません #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include<string.h> #define MAXITEM 1400 int main(void) { FILE *fp; char *fname = "testfile.csv"; char *test[11][1400]; char c; int column = 0; int row = 0; int i = 0; int y = 0; fp = fopen(fname, "r"); if (fp == NULL) { printf("%sファイルが開けません¥n", fname); return -1; } while ((c = fgetc(fp)) != EOF) { if (c == ',') { column++; putchar('\n'); } else if (c == '\n') { row++; column = 0; putchar('\n'); } else { test[row][column] = (char)c; } } printf("%s", test[0][0]); fclose(fp); return 0; }
- titokani
- ベストアンサー率19% (341/1726)
一度、fgetcとif文でアルゴリズムを考えてみましょう。 いろいろと便利そうな関数があるのですが、実のところcsvの読み込みには微妙に不便なんです。 例えば、 int column=0; int row=0; while ((c = fgetc(fp)) != EOF) { if( c == ',' ){ column++; putchar('\n'); }else if( c == '\n' ){ row=++; column=0; putchar('\n'); }else{ putchar(c); } } という感じです。これで文字列の取り出しができます。 putcharしているところを配列に入れるようにすれば、配列にも入ります。
お礼
頂いたコードをもとに記述してみました。 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include<string.h> #define MAXITEM 1400 int main(void) { FILE *fp; char *fname = "testfile.csv"; char *array[1400]; char *test[11][1400]; char c; int column = 0; int row = 0; int i = 0; int y = 0; fp = fopen(fname, "r"); if (fp == NULL) { printf("%sファイルが開けません¥n", fname); return -1; } while ((c = fgetc(fp)) != EOF) { if (c == ',') { column++; putchar('\n'); } else if (c == '\n') { row++; column = 0; putchar('\n'); } else { array[row][column] = (char)c; } } fclose(fp); return 0; }
補足
頂いたコードで無事起動しました。 ありがとうございます。columnとrowに関してですが記述理由はどういった理由でしょうか?elseで使用するためでしょうか?
補足
ありがとうございます。「文字」と「文字配列」と「文字列」の関係について理解が浅いので今一度確認してきます。