• 締切済み

CSV ⇒ 構造体 ⇒ 文字列配列

1,あいうえおあいうえお 3,かきくけこ 2,さしすせそさしすせそさしすせそ 3,たちつてと 2,なにぬねの 1,はひふへほはひふへほはひふへほはひふへほ    ・    ・    ・ といったようなCSVファイルがあります。 まずは、それを typedef struct tagSetInf{  int nPattern; // 1or2or3  char szSearch[256]; // 文字列:最大255バイト }SetInf; という構造体に格納していき、そのszSearchの値を nPatternの値に応じて3種類の文字列配列((例)search1,search2,search3)に 格納したいと思っています。 CSVのレコード数は可変です。(たぶん最大数は100くらいだとは思うのですが・・・) 以上の実現方法を教えてください。よろしくお願いいたします。 環境:Win32 API、C/C++。

みんなの回答

  • php504
  • ベストアンサー率42% (926/2160)
回答No.3

数が未定の配列をどうやって確保するかという質問なら malloc で動的に確保する方法があります。 CSVの行数だけ数えてその分の構造体をmallocで確保 構造体にCSVを読み込む 構造体から nPattern == 1, 2, 3 の数を求めそれぞれの数だけ各文字列配列を malloc で確保 mallocのお約束 使い終わったら free しましょう

kenkenpo
質問者

お礼

大変遅くなってしまい、申し訳ありませんでした。 貴重なアドバイスありがとうございました。 今更ですが、現在の進行状況を説明させていただくと、 >CSVの行数だけ数えてその分の構造体をmallocで確保 >構造体にCSVを読み込む の部分までは実装できました。 その後の >構造体から nPattern == 1, 2, 3 の数を求めそれぞれの数だけ各文字列配列を malloc で確保 の部分については、いろいろ試しているのですが上手くいかず、 文字列配列を動的に確保するには至っていません。 大変図々しいお願いだとは思いますが、アドバイス等いただけると幸いです。 ちなみに、以下のソースの最後で free(pSetInf); とすると、落ちてしますのは何故でしょうか。 よろしくお願いいたします。 // 設定ファイル.txtの情報を格納する構造体 typedef struct tagSetInf{  int nPattern;  char szSearch[128]; }SetInf; char *search1[50]; // パターン1の文字列配列 char *search2[50]; // パターン2の文字列配列 char *search3[50]; // パターン3の文字列配列 int num1 = 0; int num2 = 0; int num3 = 0; int c, nLine = 0; // 設定ファイルをオープン if((fp = fopen("設定ファイル.txt", "r")) != NULL){  while ((c = getc(fp)) != EOF){   if (c == '\n'){    nLine++; // CSVの行数をカウント   }  } } // 設定ファイルの行数により、動的に構造体のメモリを確保する SetInf *pSetInf; pSetInf = (SetInf *)mallco(nLine * sizeof(SetInf)); rewind(fp); // ファイルポインタを先頭に戻す while(fscanf(fp, "%d,%s", &pSetInf->nPattern, pSetInf->szSearch) == 2){  if(pSetInf->nPattern == 1){   search1[num1] = pSetInf->szSearch;   num1++;  }else if(pSetInf->nPattern == 2){   search2[num2] = pSetInf->szSearch;   num2++;  }else if(pSetInf->nPattern == 3){   search3[num3] = pSetInf->szSearch;   num3++;  }  pSetInf++; }

kenkenpo
質問者

補足

追加内容 混乱を招く記述をしてしまったのですが、 文字列配列の文字列は128バイト or 256バイトの固定で構いません。 よろしくお願いいたします。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★fscanf() 関数で簡単に。 ・前回のサンプルの readFile() を少し書き換えるだけで出来ると思います。  下に構造体読み込み用に書き換えたのをコピー&ペーストしておく。 // ファイルから構造体に読み込む BOOL readFile( SetInf tag[], int max, LPCTSTR lpFname[] ) {  FILE *fp;  int no;    if ( (fp = fopen(lpFname,"r")) != NULL ){   for ( no = 0 ; no < max ; no++ ){    /*    ★ここで構造体メンバにセット    ・fscanf() を使えば良いかな    ・パターン番号を tag->nPattern に直接セット    ・サーチ文字列を tag->szSearch に直接セット    */    tag++; ←移動   }   fclose( fp );   return TRUE;  }  return FALSE; } // 使い方 SetInf data[ 100 ]; if ( readFile(data,100,"abc.csv") ){  // 正常 } else{  // 異常(ファイルがない) } その他: ・エラーチェックがないので追加などして下さい。 ・以上。

参考URL:
http://www.bohyoh.com/CandCPP/C/Library/fscanf.html
kenkenpo
質問者

お礼

大変遅くなってしまい申し訳ありません。 いつも、大変参考になるアドバイス本当にありがとうございます。 CSVファイルから、構造体に読み込むのは以下の方法で 実現できました。 しかしまだ、その構造体からパターン番号に応じた文字列配列に、 動的に配列を確保して格納するという処理を実装することができません。 今のままですと、それぞれ50個までしか登録できません。 いつもお願いしてばかりで大変申し訳ないのですが、アドバイスをいただけると幸いです。 よろしくお願いいたします。 ちなみに、以下のコードの最後に free(pSetInf); とすると、落ちてしまいます。 // 設定ファイル.txtの情報を格納する構造体 typedef struct tagSetInf{  int nPattern;  char szSearch[128]; }SetInf; char *search1[50]; // パターン1の文字列配列 char *search2[50]; // パターン2の文字列配列 char *search3[50]; // パターン3の文字列配列 int num1 = 0; int num2 = 0; int num3 = 0; int c, nLine = 0; // 設定ファイルをオープン if((fp = fopen("設定ファイル.txt", "r")) != NULL){  while ((c = getc(fp)) != EOF){   if (c == '\n'){    nLine++; // CSVの行数をカウント   }  } } // 設定ファイルの行数により、動的に構造体のメモリを確保する SetInf *pSetInf; pSetInf = (SetInf *)mallco(nLine * sizeof(SetInf)); rewind(fp); // ファイルポインタを先頭に戻す while(fscanf(fp, "%d,%s", &pSetInf->nPattern, pSetInf->szSearch) == 2){  if(pSetInf->nPattern == 1){   search1[num1] = pSetInf->szSearch;   num1++;  }else if(pSetInf->nPattern == 2){   search2[num2] = pSetInf->szSearch;   num2++;  }else if(pSetInf->nPattern == 3){   search3[num3] = pSetInf->szSearch;   num3++;  }  pSetInf++; }

kenkenpo
質問者

補足

追加内容 混乱を招く記述をしてしまったのですが、 文字列配列の文字列は128バイト or 256バイトの固定で構いません。 よろしくお願いいたします。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

残念ながらお答えできません。 自分で考えて出来た所までを書かないと、このサイトでは削除されてしまいます。 以下は、削除時に届くメールから抜粋しました。 >当サイトは、会員の方同士の助け合いによる知識交換を提供させていただく質疑応答の場として運営しており、特定の会員の方に質問、回答の投稿を義務づけ、他の会員の方に何かを依頼してやってもらうというような場でございません。 >課題やレポートなどを質問として投稿する事自体は禁止しておりませんが、「○○についてやってください」など、課題文を丸写しにしたような質問についてはマナー違反であると考えております。 >質問を削除いたしますと回答もあわせて削除されてしまいます。せっかくご回答いただきましたのに申し訳ございませんがご了承くださいますようお願いいたします。 >※当ルールにつきましては、皆様にご理解いただきやすいよう「課題」「レポート」という語句を使用いたしておりますが、課題やレポートではなくても、上記に該当すると考えられるものは、投稿をご遠慮いただいております。

kenkenpo
質問者

お礼

申し訳ありません。 ある程度までは自分で考えていたものがあったのですが、それを載せませんでした。 今後は気をつけたいと思います。

関連するQ&A

  • CSVファイルを読み込んで計算するには、構造体か?

    はじめまして。C++プログラミングの質問です。 初心者レベルの質問で申し訳ないのですが、お付き合いください。 CSVファイルを読み込んで、書かれている値を使ってある計算を行う、 ということをしたいのですが、処理方法をどうするか悩んでいます。 CSVファイルに書かれる最大行86400行、最大列6000列です。 また、開発環境はLinuxとなります。 私は「CSVファイルの項目を構造体に格納するクラス」と、「構造体の値を使って計算 するクラス」を考えました。 しかし、構造体ですと最大86400行のものを格納するのは、メモリを食うだけで無駄だという 指摘を受けました。 直接ファイルから値をとってきて、計算クラスに処理させるほうが無難と言われましたが、 「CSVファイルの項目を構造体に格納するクラス=データベース」と考えており、 後々拡張する場合に融通が利くのではないでしょうか。 経験が浅いので、断固たる主張ができないのですが・・・ 構造体に入れることばかり考えていたので、開発のボリュームを抑え、かつ、メモリを食わない 方法を全く思いつきません。 有識者の方へアドバイスを受けたいのですが、 ・大量のデータを読み込む場合、構造体等に格納する方が後ほど助かるか、 それとも、直接ファイル読み込みした方がよいか ・構造体格納のほかに相応しいやり方はないか この2点をメインにお答えいただけないでしょうか。 何か良いやりかたがありましたら教えていただきたいです。 よろしくお願い致します。

  • 文字列になっている配列を‥

    以下の値がDBに文字列の項目に登録されています。 DB から値を取得したのはいいのですが文字列なので foreach でグルグルしようとすると怒られてしまいます。 配列の型に変換できればいいのですが(array)だとうまく行かないしどうすればいいかどなたかご教授願えないでしょうか。 よろしくお願いします。 ■値(文字列でDBに格納されてます‥) array( 1=>'a', 2=>'b', 3=>'c', 10=>array( 'A'=>1, 'B'=>'hoge1', ), 11=>array( 'A'=>2, 'B'=>'hoge2', ), 12=>array( 'A'=>3, 'B'=>'hoge3', ), )

    • 締切済み
    • PHP
  • 文字列を配列として扱う方法について

    文字列を配列に格納したいのですが、うまくいかずに困っています。 例えば、 a[1]=1番目のファイル.csv; a[2]=2番目のふく; a[3]=凄く長い名前.csv; としたいと考えています。 どのようにすればいいのでしょうか? 数字を配列に格納することはできます。

  • VCの構造体【否 .Net】文字列

    http://okwave.jp/qa2526132.html での質問の発展です。 構造体の中に文字列を入れたいのです。 4の倍数にする必要がある、と聞いたので typedef struct {  char a[80];  int b;  int c; } Data_t; とし、VB側で Public Type vbData  a As String * 80  b As Long  c As Long End Type としましたが、うまく受け取れません。 どうかお力添えを。

  • 入れ子の構造体について

    例えば、入れ子の構造体を1つ使いたい場合、 struct bbb{ int b; }; typedef struct aaa{ struct bbb a; }AAA; AAA dt; と書くと、「dt.a.b = 10」とやれば、値等を設定できると思いますが、 入れ子の構造体を2つ使いたい場合も、同じように書けるのでしょうか? struct ccc{ int c; }; struct bbb{ struct ccc b; }; typedef struct aaa{ struct bbb a; }AAA; AAA dt; dt.a.b.c = 10; と書けるのでしょうか?こんがらがってしまって、どう書いていいのか・・。 2つでも出来るのであれば、コードの書き方を教えて頂けませんか?

  • 構造体について(配列)

    こんばんはです。 下記のように 例 typedef struct person{ char name[256]; char pass[256]; }mydata; mydata men[5]; と、言う具合にあったとします。 menには全て入力されていて、例えばmen[3].nameとpassを消去したいとします。 その際、strcpy(men[3].name,"")とかしてるのですが、結局は、men[3]にはNULLが入るだけで、クリアというわけにはいかないのです。 全部クリアはmemsetをつかってできるのですが、場所指定ではどのようにするのでしょうか? 最終的にはmen[2]をクリアしたら、men[3]以降をずらして格納したいと思ってます。 切り取ったりしたいですが、できるのでしょうか?その場合、配列数は減らないのでしょうか? 消去した場所にコピーという形でずらしていったらいいかもですが・・。 アドバイスいただけたらうれしいです。 よろしくおねがいいたします。

  • 文字列の配列

    文字列の配列 1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4 のようにIPアドレスが一行に一つづつ書き込まれたテキストがあります。 ここから、それぞれのIPアドレスを文字列として配列に書き込みたいのですが、どうしたらよいのでしょうか。 IPアドレスの数だけ配列を始めに宣言して、それぞれに書き込んでいくのでは手間がかかりすぎてしまいます。 単純に数値の羅列なら scanfを使い、配列に格納できるのですが、文字列になるとどうしたらいいのかわかりません。 よろしくお願いいたします。

  • ラダー回路 文字列データのCSVへの書き込み

    データレジスタD0以降に格納されたアスキーデータ"00001"をCSVファイルに書き込みたいのですが、三菱Qシリーズシーケンサだと文字列のCSV出力ができません。 仕方なくアスキーからBIN形式にしてからCSV書込みをしてみようと試みたのですが、正しい値に変換できません。(添付図参照) データを "00001" としてCSVファイルに書き込むにはどうすればよいのでしょうか?

  • 配列への文字列の追加ってどうやって追加するの?

    配列に文字列をいれたいのですが char a[100]; sprintf(a,"AB"); と書くと a[0]にAが a[1]にBが a[2]に\0が格納されますよね。 「配列に一度格納された文字列に新たな文字列を追加」したいのです。 つまり この\0を上書きしてa[2]から CD を追加し、結果 a[0]にAが a[1]にBが a[2]にCが a[3]にDが a[4]に\0が 格納されているようにしたいのです。 半角英数だったらできるのですが全角だとどうやるのでしょうか。 やりたい事は以下のようなものです。 "あい"を1度目の処理で配列に文字列を格納し、次の処理で"うえ"を追加し、 配列aをprintfするとき「あいうえ」が出力されるようにしたいのです。 どなたか教えてください(>_<

  • 文字列の構造体キャスト

    文字列を構造体にキャストした際に、メンバ変数は以下のようには、 取得できないのでしょうか? typedef struct { int year; /* 学年 */ int clas; /* クラス */ int number; /* 出席番号 */ char name[64]; /* 名前 */ } student; int main(void) { student *data=NULL; char c[] = "123456789012abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij1234"; char* tmp; tmp = &c[0]; student_print(data, tmp); return 0; } void student_print(student *data, char *mkg) { void* buff = NULL;    buff = (student*)mkg; printf("[year]:%s\n", buff ->year);←ここ return; }