- ベストアンサー
C言語でカンマ区切りの配列に挿入する方法
- C言語でカンマ区切りのデータを配列に挿入する方法について教えてください。
- 配列にデータを挿入する際にエラーが発生しています。解決方法を教えてください。
- 初心者のため、C言語で配列にデータを挿入する方法がわかりません。助けてください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
で、幾つも問題点があります。このプログラムは、修正してエラーが出ないようにしても、正常に動きません。 問題点1点目。 test[piyo][hoge] = NULL; この行はメモリを壊します。OSが例外を発生してプログラムが停止します。 testの配列は「test[0][0]~test[piyo - 1][hoge - 1]」までしかありません。 1次元目の要素番号に指定できるのは「0」から「piyo - 1」までです。 2次元目の要素番号に指定できるのは「0」から「hoge - 1」までです。 問題点2点目。 while (fgets(buf, hoge, fp) != NULL) { 「bufのメモリに、何度も読み直し」をしているので、strtokで返って来たポインタを配列に記録しても無意味です。 「2回目のfgetsを行なったら、1回目にfgetsした後のbufの内容が壊れてしまう」という事を理解して下さい。 つまり「fgetsは1行につき、1回しかやってはいけない」のです。 なので「while文で、同じメモリに読み込むfgetsを繰り返す事はできない」です。 問題点3点目。 if ((fp = fopen("testfile.csv", "r")) == NULL) { printf("\aファイルをオープンできません\n"); }else{ 略 } fclose(fp); オープンエラーが出た時、if文の処理が終わると、fpがNULLなのに「fclose(fp)」を実行してしまいます。エラーの時は「後始末だけやって、続きの処理をしない」ようにしないといけません。 問題点4点目。 for (k = 0; k < hoge; k++) { ary[k] = strtok(buf, ","); } strtokの使い方が間違ってます。 以下を参照して下さい。 http://www9.plala.or.jp/sgwr-t/lib/strtok.html 上記を踏まえて、修正して動作するようにしたのが、以下のプログラムです。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define piyo 11 #define hoge 2900 int main(void) { FILE *fp; //1行hoge文字分のバッファを、piyo行分、用意する。 //念のため、バッファは「1文字分余計に」確保しておく。 char test[piyo][hoge + 1]; //分離したトークンのポインタを覚えておく配列。 //piyo行分、1行につきhoge個分。 char *ary[piyo][hoge]; int i, k; //aryを初期化する。 for (i = 0;i < piyo;i++) { for (k = 0;k < hoge;k++) { ary[i][k] = NULL; } } //ファイルを開く if ((fp = fopen("testfile.csv", "r")) == NULL) { printf("\aファイルをオープンできません\n"); //エラーならretuenして、それ以上処理しない return(0); }else{ //piyo行分、繰り返す for (i = 0;i < piyo;i++) { //testのi行目のバッファに読み込む。 //1行繰り返すごとに、test[0]の先頭、test[1]の先頭、test[2]の先頭 //のように、読み込むバッファのポインタを変える。 if (fgets(&test[i][0], hoge, fp) == NULL) break; //末尾の改行を\0(EOS)に書き換えて、改行を削り取る。 strtok(&test[i][0], "\n"); //列番号kを初期化。 k = 0; //一回目のstrtokの呼び出し。 ary[i][k] = strtok(&test[i][0], ","); //strtokがNULLを返すまで繰り返す。 while (ary[i][k] != NULL) { //列番号を1つ増やす。 k++; //列番号が限界に達したら諦める。 if (k >= hoge) break; //2回目以降のstrtokの呼び出し。 ary[i][k] = strtok(NULL, ","); } } fclose(fp); //結果を表示する。 for (i = 0;i < piyo;i++) { for (k = 0;k < hoge;k++) { if (ary[i][k] != NULL) { printf("ary[%d][%d]=[%s]\n",i,k,ary[i][k]); } } } } return(0); } で、このプログラムは、結局は http://okwave.jp/qa/q9216423.html の当方の回答と「ほぼ同じ事」をしています。 違うのは「今回のは、1行づつ11回読み込んで処理するが、前回のは、必要なメモリを動的に確保して、一気に全部読み込んで処理する」という点と「今回のは、改行の扱いをfgets任せにしているが、前回のは、自前で改行を判定して処理する」という点です。
その他の回答 (5)
- maiko0333
- ベストアンサー率19% (839/4401)
そう、の次です。
- m-take0220
- ベストアンサー率61% (480/785)
> test[piyo][hoge] = NULL; 配列数の問題はすでに指摘されていますが、VCではNULLが(void*)0と定義されているので、 > 警告C4047'=': 間接参照のレベルが 'char' と 'void *' で異なっています。 になるものと思われます。文字の場合は'\0'を使用するべきでしょう。 そもそも、何をしたくて記述したコードなのかがわかりません。配列全体を初期化したいのであれば、 > char test[piyo][hoge] = {'\0'}; にするべきです。
- maiko0333
- ベストアンサー率19% (839/4401)
strtok(buf, ",");は行の最初だけ、 2つめ以降ははstrtok(NULL, ",");と書く。 結果がNULLになったら次の行に行く。
- maiko0333
- ベストアンサー率19% (839/4401)
test[piyo][hoge] = NULL; ですが、配列は0からなので、test[piyo][hoge] と宣言したらtest[piyo-1][hoge-1] までしかありません。
- chie65536(@chie65535)
- ベストアンサー率44% (8800/19959)
{と}でインデントしてみましょう。 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define piyo 11 #define hoge 2900 int main(void) { FILE *fp; char test[piyo][hoge]; char buf[hoge]; char *ary[hoge]; int i, k; test[piyo][hoge] = NULL; if ((fp = fopen("testfile.csv", "r")) == NULL) { printf("\aファイルをオープンできません\n"); }else{ while (fgets(buf, hoge, fp) != NULL) { for (k = 0; k < hoge; k++) { ary[k] = strtok(buf, ","); } } fclose(fp); return(0); } どうですか? 「どっかで{と}がズレてる」って気が付きませんか? あと、以下のように「インデントに誤魔化されて、}が足りないのが判らなくなる事がある」ので注意。 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #define piyo 11 #define hoge 2900 int main(void) { FILE *fp; char test[piyo][hoge]; char buf[hoge]; char *ary[hoge]; int i, k; test[piyo][hoge] = NULL; if ((fp = fopen("testfile.csv", "r")) == NULL) { printf("\aファイルをオープンできません\n"); }else{ while (fgets(buf, hoge, fp) != NULL) { for (k = 0; k < hoge; k++) { ary[k] = strtok(buf, ","); } } fclose(fp); return(0); }
お礼
ありがとうございます。現在上記とは少しコードは違いますが、}が足りていませんでした。意識できるようにしていきます。
お礼
ありがとうございます。二つ目というのは 、 が読み込まれた次の文字列ということでしょうか?一度確認してきます。