• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語 配列挿入)

C言語でカンマ区切りの配列に挿入する方法

このQ&Aのポイント
  • C言語でカンマ区切りのデータを配列に挿入する方法について教えてください。
  • 配列にデータを挿入する際にエラーが発生しています。解決方法を教えてください。
  • 初心者のため、C言語で配列にデータを挿入する方法がわかりません。助けてください。

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

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

で、幾つも問題点があります。このプログラムは、修正してエラーが出ないようにしても、正常に動きません。 問題点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)
回答No.6

そう、の次です。

回答No.4

> test[piyo][hoge] = NULL; 配列数の問題はすでに指摘されていますが、VCではNULLが(void*)0と定義されているので、 > 警告C4047'=': 間接参照のレベルが 'char' と 'void *' で異なっています。 になるものと思われます。文字の場合は'\0'を使用するべきでしょう。 そもそも、何をしたくて記述したコードなのかがわかりません。配列全体を初期化したいのであれば、 > char test[piyo][hoge] = {'\0'}; にするべきです。

  • maiko0333
  • ベストアンサー率19% (839/4401)
回答No.3

strtok(buf, ",");は行の最初だけ、 2つめ以降ははstrtok(NULL, ",");と書く。 結果がNULLになったら次の行に行く。

losloson
質問者

お礼

ありがとうございます。二つ目というのは 、 が読み込まれた次の文字列ということでしょうか?一度確認してきます。

  • maiko0333
  • ベストアンサー率19% (839/4401)
回答No.2

test[piyo][hoge] = NULL; ですが、配列は0からなので、test[piyo][hoge] と宣言したらtest[piyo-1][hoge-1] までしかありません。

回答No.1

{と}でインデントしてみましょう。 #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); }

losloson
質問者

お礼

ありがとうございます。現在上記とは少しコードは違いますが、}が足りていませんでした。意識できるようにしていきます。

関連するQ&A

専門家に質問してみよう