• 締切済み

mallocの使い方

すいません初心者な僕に教えて頂きたいことがあるます。 1行64バイトのファイル(行数可変)のデータに何回も文字列の検索を行ういアウトプットするプログラムを作っています。 fgetsを使い何回もファイルを読み込んで一行ずつ比較するというようにできたにはできたのですが、 行数可変で多い場合100000行超えたりするファイルに対してはえらい時間がかかります。 mallocが良いとはわかったのですが、なかなかうまく組めません。 ご教示願えませんでしょうか。 ↓のような文字列があり 型番 要素1 要素2 要素3 A 1044 100 123 A 1055 277 155 B 100 115 224 C 115 277 885 B型番の要素2がB型番の要素と一致した時B型番の要素2と要素3に一致するC型番の文字列を探しだすというようなプログラムです。 これがA、B、C共にソートされずランダムに並んでいます。 検索する度に毎回ファイルを読み込まず、一括でメモリに溜め込み、その中から文字列を抜き出し比較したいと思っています。。 長くなりましたが宜しくお願いします。

みんなの回答

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

行数が不明なら数えればいいんです。 #include <stdio.h> #include <malloc.h> int main(void) { FILE* fp; char buf[64]; int count = 0; char* lines; int i; fp = fopen("test.dat", "r"); while (fgets(buf, 64, fp)) { count++; } fseek(fp, 0, SEEK_SET); lines = (char*)malloc(count * 64); for (i = 0; i < count; i++) { fgets(lines+i*64, 64, fp); } fclose(fp); for (i = 0; i < count; i++) { printf("%s", lines+i*64); } free(lines); return 0; }

  • crew21
  • ベストアンサー率26% (58/222)
回答No.6

質問者さんNo.2さんの回答で理解できました? 出来たのならいいんですが... やっぱり何度読んでも、意味がわからなかったです。 ちなみに昼休みに、自社の人間5人くらいに、訂正後のも含めた質問者さんの質問文を見せたのですが、 質問内容の意味解釈の議論がわき起こってしまい、結局質問の意味がわからない、で終わりました。 No.2さんのように聡明な方も中にはいらっしゃいますが、 そういう人ばかりじゃないですから、もっと質問者を読む側に立った書き方をした方がいいですよ。マジで。 ごめんね、お説教で。 >まず一番上のTRIA要素を抜き出し(1行)、その他のTRIA要素内で1点でも構成GRIDIDが重複するTRIAを抜き出します。(個数は変動) >その後、最初に抜き出したTRIAとそれと重複点のあるTRIAからGRIDIDを抜き出し、GRID行からそれぞれの座標点を抜き出してそれを計算させるというプログラムを組んでいます。 >下に記入されている間隔でカラム分けが最初にされているので、ブランクを含めた文字列として"TRIA 1"というように各行で検索を行い。 >さらのその行を抜き出し11-17を抜き出すというようにやっています。 例えば上の4行を読んでて、1行目はわからないでもない。 でもそこから先は読み進めるほどに、推測の上に推測を重ねていくことになるので理解しにくいのです。 >その他のTRIA要素内で1点でも構成GRIDIDが重複するTRIAを抜き出します。 (具体例) >その後、最初に抜き出したTRIAとそれと重複点のあるTRIAから (具体例) >GRIDIDを抜き出し、 (具体例) >GRID行からそれぞれの座標点を抜き出して (具体例) すべの問題に上記のことをやるべしとは言わないけど、このタイプのこれくらいの感じで書かないとマジわからんよ。 自分の分かってることは、他人の分かってる事じゃないからね。

sac411
質問者

お礼

そんな大事になってしまわれましたか・・・ 申し訳ありません。 これからは質問に対しても精進致します。

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

★『型番』が消えちゃいましたね。 ・とにかくTRIA、GRIDを格納する構造体を定義して全データをメモリに読み込んで  処理すれば良いのでは?  この質問のタイトルは『mallocの使い方』ですよね。  まずは3点の情報を格納できる構造体を考えて下さい。  3点の情報は小数点ですが double 型は使わずに整数に格納します。  (11~17とは1.1~1.7のことですよね) ・例えば  typedef struct grid_t {   int a, b, c;  } grid_t;    という3点の情報を格納するGRID構造体を定義します。  そして grid_t Grid[ 100000 ]; などと配列で宣言、または malloc 関数で動的確保します。  後はファイルから行単位で GRID データを Grid[0]~Grid[xxxxx]に順番に読み込みます。  malloc 関数の使い方は下のサンプルを参考にして下さい。 サンプル: #define MAX_GRID (100000) // 最大値(10万件) // 構造体 typedef struct grid_t {  int a, b, c; } grid_t; // メイン関数 int main( void ) {  grid_t *Grid;  int max;    if ( (Grid = (grid_t*)malloc(sizeof(grid_t) * MAX_GRID)) != NULL ){   // ファイルをオープン   for ( max = 0 ; max < MAX_GRID ; max++ ){    // 行単位でGRIDデータを読み込む→要素1,2,3に分ける    Grid[ max ].a =『要素1』;    Grid[ max ].b =『要素2』;    Grid[ max ].c =『要素3』;   }   // ファイルをクローズ   /*   ここで GRID 配列(grid_t構造体)を使って要素抜き出しを処理。   GRID 配列の有効範囲は Grid[0]~Grid[max - 1]です。   */   free( Grid );  }  return 0; } その他: ・Grid 配列にすべてのデータを格納したら Grid[0]~Grid[max - 1]までを探索して下さい。  上記のサンプルを参考に頑張って下さい。 ・malloc関数の使い方は malloc(確保バイトのサイズ) とすればいいだけです。  処理し終えたら Grid を free() して下さい。 ・以上。

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

★回答者No.2です。 ・確認の為にお聞きします。  検索の手順は  (1)型番『A』の『1044』を検索して見つかったらその要素2,3を抜き出す。  (2)抜き出した要素2,3を型番『B』内で要素2の『100』を検索する。  (3)見つかったら型番『B』の要素2,3を抜き出して型番『C』内で要素2の『115』を…。  上記のように(1)(2)(3)を繰り返し、足し算して出力したいのですよね?  検索の手順はあっていますか? ・ちなみに要素2,3を抜き出すようですが要素3も同様に検索するのですか?  それとも要素2だけを次の検索対象として『A』『B』『C』を繰り返すの?  不明な点がちょっとあるね。 ・以上。

sac411
質問者

お礼

申し訳ありません。 カラムがうまく表示できていませんでした。 TRIA______1______1______2______3 TRIA______2______3______4______5 GRID______1____1.1____1.2____1.3 GRID______2____1.4____1.5____1.6 GRID______3____1.7____1.8____1.9 GRID______4____2.1____2.2____2.3 GRID______5____2.4____2.5____2.6 "TRIA______1" *"_"はプランクです。

sac411
質問者

補足

本当に説明不足が酷いようで申し訳ありません。 やりたいことを明確に書きます。 要素名  TRIAID 構成GRIDID3点 TRIA 1 1 2 3 TRIA 2 3 4 5 GRIDID GURID座標3点 GRID 1 1.1 1.2 1.3 GRID 2 1.4 1.5 1.6 GRID 3 1.7 1.8 1.9 GRID 4 2.1 2.2 2.3 GRID 5 2.4 2.5 2.6 |_____|______|______|______| ということが記入されているファイルがあります。(行数可変) TRIAは3点のGRIDにより構成されています。 まず一番上のTRIA要素を抜き出し(1行)、その他のTRIA要素内で1点でも構成GRIDIDが重複するTRIAを抜き出します。(個数は変動) その後、最初に抜き出したTRIAとそれと重複点のあるTRIAからGRIDIDを抜き出し、GRID行からそれぞれの座標点を抜き出してそれを計算させるというプログラムを組んでいます。 下に記入されている間隔でカラム分けが最初にされているので、ブランクを含めた文字列として"TRIA 1"というように各行で検索を行い。 さらのその行を抜き出し11-17を抜き出すというようにやっています。 その為行数の多いものになると時間がかなりかかってしまいます。 長くなりましたが、これでご理解頂けないようならば本当に僕の説明力の無さを嘆くことにします・・・

  • crew21
  • ベストアンサー率26% (58/222)
回答No.3

ごめん、質問の意味がホンキでわからないや(ここに来て半年くらい経つけど初めてだよ) >型番 A 1044を検索し、引っかかったら要素2,3を抜き出します。 まずここで分からない。 どこの範囲を検索して「引っかかったら」と言っているのですか?質問者さんが挙げた例で言うと、12個の数値を全て検索するのですか? >抜き出した要素2,3をB型番要素1と合致するか検索を行います。 「抜き出した要素2,3」てことは複数(2つ)抜き出されたんですよね。それをどうやって「抜き出した要素をC型番の要素1と比較」できるんですか? 例で言うと要素2と3は各々100と123に相当しますよね。B型番要素1とは100ですよね。 2つの要素と1つの要素の一致不一致をどうやって比較するんですか? No.2さんが回答出してるようなのでこれ以上の補足は求めないけど、マジ意味不明です。 一言で言うとね「なにがしたいのか」が見えてこないんですよ。 世の中いろんな疑問があるけど、読んでるうちに「ああ、この疑問(問題)は、この部分が核というかミソで、質問者さんはこの辺で困ってるんだな」というのがわかってきます。 ところが、それが質問者さんの文章の中に全然見えてこないんです。 要はその検索は、どんなことが目的なのかが。

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

★アドバイス >これでご理解頂けますでしょうか・・・・  ↑  何とか理解できたかも。 ・型番の要素1~3が整数値なら構造体の整数で管理してメモリに格納します。  例えば  typedef struct foo_t {   int n1, n2, n3; // 要素1,2,3   char name[ 1 ]; // 型番の文字列  } foo_t;    として foo_t *data[ 100000 ]; というポインタへの配列を宣言します。  あとはファイルを順番に読み込んで data 構造体を検索します。 ・malloc の使い方としては  foo_t *p;    len = strlen("型番の文字列");  p = malloc(sizeof(foo_t) + len);  として  p->n1 = 要素1;  p->n2 = 要素2;  p->n3 = 要素3;  strcpy( p->name, "型番の文字列" );  data[ count++ ] = p;    とします。  ちなみに構造体の name は可変長として使うために一番最後の要素にします。 ・以上。参考に。

  • crew21
  • ベストアンサー率26% (58/222)
回答No.1

ちなみにB型番の要素2って115だよね。 >B型番の要素2がB型番の要素と一致した時B型番の要素2と要素3に一致するC型番の文字列を探しだすというようなプログラムです。 ...ダメだ..何度読んでも全然意味がわからない。 とりあえずデータを羅列してくれたのはいいとして、もう少しデータ量を増やして、結果的に例えばどうなるかを、具体例を示してくれませんか。

sac411
質問者

補足

ありがとうございます。 もう少し詳しくデータを記載します。 型番 要素1 要素2 要素3 A 1044 100 123 A 1055 277 155 B 100 115 224 C 115 277 885 型番 A 1044を検索し、引っかかったら要素2,3を抜き出します。 抜き出した要素2,3をB型番要素1と合致するか検索を行います。 合致した場合、今度はB型番の要素2,3を抜き出し、抜き出した要素をC型番の要素1と比較し、合致した場合、C型番要素2,3を抜き出してそれを足した数をアウトプットしたいと考えております。 その為、A型番後B型番、C型番と検索するのに毎度ファイルを開いている状況です。行数が短ければ良いのですが、10万行を超える場合等はえらく時間がかかってしまいます。 これでご理解頂けますでしょうか・・・・ 説明不足で申し訳ありません。

関連するQ&A

  • 最終行に合計(最終行が列によって異なる場合)

    エクセルVBAに於いて質問させて頂きます。 タイトルにも書かせていただきましたが、 A列に行数可変のデータ(文字列)があり、 B列に行数可変のデータ(数字)があり、 A列の行数>=B列の行数の条件とき、 A列の最終行+2の位置のA列に文字で合計 A列の最終行+2の位置のB列にsumを表示する場合、 どのようにすれば出来ますでしょうか。 A列の最終行+2の位置のA列に文字で合計は With Range("A3") .End(xlDown).Offset(2, 0).Formula = "合計" End With でいけると思うのですが、 A列の最終行+2の位置のB列にsumを表示する場合どのようにすればいいのかわかりません。 ご教授のほどお願い致します。

  • 一致した行を返したい

    excel2007を使っています おしえてください    A   B   C 1   1   3 2   2   8 3   2   3 4   1   3 5   7   8 6   2   8 7   1   3 このような表がありA1の1と同じ1をA列2行目から検索 B1の3と同じ3をB列2行目から検索 どちらも値が一致した行(検索開始行から数えて何番目)をC1に返したい (この場合3と6がありますが早く一致した3を返したい) C2は4となります Cに入れる数式を是非教えてください

  • csvファイルを開かずに文字を検索し行を抽出したい

    フォルダの中に複数のCSVファイルが有ります。 これらのファイルを開かずに文字列を検索し、検索対象の文字と完全一致する 文字がある行をまとめてひとつのファイルに抽出する方法を探しています。 例:Aフォルダ内にファイル1、ファイル2、ファイル3、、、と複数のファイルがある。 ファイルのフォーマットはすべてCSV。ファイルにはシートは一つのみ。日付なのですべて異なります。       A         B  C   D   E   F  G   H   I   J  K   L 加工年月日時分 品種 コード A列 B列 C列 D列 E列 F列 G列 本数 作業者    ・    ・    ・ A~Lまであり、Cのコードが指定した検索文字と完全一致するものを抽出したいです。 急ぎの内容の為、VBAやコマンドプロンプトなど、自分なりに色々なサイトにある プログラムを組み換えようとしましたが初心者の為すぐに理解して応用はとても 無理でした。知恵を貸して頂きたいです。

  • Excel 2007 vlookupについて

    Excel 2007 vlookupについて 同じシートでA列とB列の2列にある型番で一致するものをC列に表示させたいです。 実際A列の型番は一意の番号です。 B列の型番は同じ番号がございます。 型番1は100行ぐらい。 型番2は300行ぐらい。 C列にどのようなvlookupを記載すればよろしいでしょうか。 ※C2以降に結果が表示されるようにしたいです。

  • VBスクリプト 文字列操作

    VBスクリプト(全くの初心者です)について教えてください。 例えば "test.csv" にて 1,a 1,b 1,c 1,d 2,a 2,b 3,d 3,e 4,a 4,f 4,g のファイルがあるとします。 最初の1列目の数字(文字列)の行数は可変です。 最終的に "test2.csv" 1,a,b,c,d 2,a,b 3,d,e 4,a,f,g というファイルを作りたいのですが,ずばりコードを教えていただけないでしょうか。

  • 別シート同士のセルを比較して一致したらセルに代入をしたいと考えています

    別シート同士のセルを比較して一致したらセルに代入をしたいと考えています。 excelのVBAを使って行いたいのです book1のsheet1に A列     B列    C列       D列 2000     NEC   VL100 5000     Sony   vaio-200 3000     東芝     letsnote 単価、メーカー、型番、空き列があり 200行くらいです。 book2のsheet1に 同じく、単価、メーカー、型番がありますが 単価がsheet1とは異なり、違うメーカー型番の情報が 4000行くらいあります A列     B列    C列 5225     XXXX   XXXX 2200     NEC   VL100 5200     Sony   vaio-200 2684     XXXX   XXXX 2566     XXXX   XXXX 6000     東芝     letsnote ・・・・・・ ・・・・・・ そこで book1のB,C列のメーカーと型番が一致するものを book2のsheet1のB,C列から探し 一致したら、book1のsheet1のD列に book2 sheet1のA列の値を入れのです。 参考になるスクリプトを教えて頂けると大変助かります、 よろしくお願い致します。

  • エクセルで前方一致のVlookupはできませんか

    * すぐに回答を! エクセルで前方一致のVlookupのような関数はないでしょうか。 具体的には、A列とB列にデータがあり、A列のデータの文頭部分の文字列が B列のデータのどれかと一致した場合に、C列に一致したB列のデータを返したいです。 データの行数が非常に多い(3,4万行)であるため、できるだけ動作の軽い 関数であればなお助かります。 A          B           C zzzfewfe      dadaf         zzzf dadaf3233      a11111k        dadaf aabbbb-fefe3     zzzf         aabbbb a11111k33r3      aabbbb       a11111k 宜しく御願い致します。

  • 別ブック2列がマッチした文字を入力する

    BブックのC列7行目から文字(15ステップ毎文字が入替る)がまたF列8行目からは年月(2017/4~2018/3)、AブックのA列4行目から年月がまたB列4行目からは文字が添付のように連続して入力されています。BブックC列文字とAブックB列文字が一致、BブックF列年月とAブックA列年月が両方一致した行のAブックC列の文字をBブックのE列に順々に入力していきたいのですが。 どなたかVBAコードが解る方ご教授願います。 環境はwindows7 office2013です。

  • Excel VBAで列を行に変換するには

    不特定多数の行数(百列以上)と列数(千列以上)を持ったデータを以下にある結果1を結果2のように列と行を置換したいのですがどうしたらよろしいでしょうか? もしよろしければ、プログラムを教えていただけたら助かります。 よろしくお願いします。 ///////////結果1//////////////////// A1 B1 C1 →不特定の列数 A2 B2 C2 A3 B3 C3 ↓ 不特定の行数 ///////////結果2/////////////////// A2 A2 A3 B1 B2 B3 C1 C2 C3

  • エクセルのデータ比較

    シート1のA行のデータとB行のデータをすべて比較して、同じデータがあれば C列にそのデータを書き出したいのですが、どうすればよろしいのでしょうか。 行数(比較するデータの数)はそれぞれ数千行あります。 例(a~hはデータです) シート1     A列 B列 a c b d  c f d h の場合、比較した結果をC列に次のように表示させます。 A列 B列  C列 a c c b   d d c f d h どなたかよろしくご教示くださるよう、お願いします。