- 締切済み
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共にソートされずランダムに並んでいます。 検索する度に毎回ファイルを読み込まず、一括でメモリに溜め込み、その中から文字列を抜き出し比較したいと思っています。。 長くなりましたが宜しくお願いします。
- みんなの回答 (7)
- 専門家の回答
みんなの回答
- php504
- ベストアンサー率42% (926/2160)
行数が不明なら数えればいいんです。 #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.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行からそれぞれの座標点を抜き出して (具体例) すべの問題に上記のことをやるべしとは言わないけど、このタイプのこれくらいの感じで書かないとマジわからんよ。 自分の分かってることは、他人の分かってる事じゃないからね。
- Oh-Orange
- ベストアンサー率63% (854/1345)
★『型番』が消えちゃいましたね。 ・とにかく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.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』を繰り返すの? 不明な点がちょっとあるね。 ・以上。
お礼
申し訳ありません。 カラムがうまく表示できていませんでした。 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" *"_"はプランクです。
補足
本当に説明不足が酷いようで申し訳ありません。 やりたいことを明確に書きます。 要素名 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)
ごめん、質問の意味がホンキでわからないや(ここに来て半年くらい経つけど初めてだよ) >型番 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)
★アドバイス >これでご理解頂けますでしょうか・・・・ ↑ 何とか理解できたかも。 ・型番の要素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)
ちなみにB型番の要素2って115だよね。 >B型番の要素2がB型番の要素と一致した時B型番の要素2と要素3に一致するC型番の文字列を探しだすというようなプログラムです。 ...ダメだ..何度読んでも全然意味がわからない。 とりあえずデータを羅列してくれたのはいいとして、もう少しデータ量を増やして、結果的に例えばどうなるかを、具体例を示してくれませんか。
補足
ありがとうございます。 もう少し詳しくデータを記載します。 型番 要素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万行を超える場合等はえらく時間がかかってしまいます。 これでご理解頂けますでしょうか・・・・ 説明不足で申し訳ありません。
お礼
そんな大事になってしまわれましたか・・・ 申し訳ありません。 これからは質問に対しても精進致します。