- ベストアンサー
行数の変動にも対応したファイル読み込みのやり方
学校でファイル読み込みの課題を今しているのですが、ファイルの行数が増えた場合にも対応していて、且つ無駄な領域を使わないようなファイル読み込みをするのに困っています。 流れとしては csvファイルから内容を読み込む ↓ カンマで分割し、構造体に格納 ↓ その格納した構造体を返す という動きをしたいのですが、構造体をmallocで動的にメモリ確保する時にも、行数の取得が必要になってきて・・・ 一度行数を調べてから、処理を行う方法を取るか、他のchar型配列か何かに一度全てを格納して、そのときにカウントした行数を使って構造体のメモリを動的に確保する・・・くらいまでは思いついたのですが、始め全てを格納する時点でもまた動的にメモリを格納する方法が思いつかなくて・・・・ やはりどこかで多めに領域を取り、そこに格納する手を使うしかないのでしょうか? ご教授お願いします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
データを格納する構造体とその構造体の配列(ダブルポインタ)を動的に確保していけばいいように思います 初回は struct tagData** pArStruct = (struct tagData**)malloc(sizeof(struct tagData*) ); struct tagData* pStruct = (struct tagData)malloc( sizeof(struct tagData) ); int nCnt = 0; pArStruct[nCnt] = pStruct; と確保します このpStructにデータを読み込みます 次回からは nCnt++; // struct tagStructの配列を拡張 pArStruct = (struct tagStruct**)realloc(pArStruct, sizeof(struct tagStruct*) * ( nCnt + 1 ) ); // 次の行用の構造体を確保 pStruct = (struct tagStruct)malloc( sizeof(struct tagStruct) ); pArStruct[nCnt] = pStruct; といった具合で拡張していきます エラーチェックなどは省略していますのでmalloc/reallocなどからの戻り値がNULLでないのかをチェックしましょう 不要になった動的に確保した領域はfreeなどで開放しましょう for ( int n = 0; n < nCnt; n++ ) { // pStruct = malloc( sizeof(struct tagData) );で確保した // 配列の要素を開放 free( pArStruct[n] ); } // malloc/reallocで確保した pArStruct自体を開放 free( pArStruct );
その他の回答 (5)
- eicha_2007
- ベストアンサー率14% (23/154)
速度を気にしないなら,適当なサイズのバッファにCSVからfreadし,格納されたデータ中の改行コードをカウントして行数を得てmallocかな。
- Tacosan
- ベストアンサー率23% (3656/15482)
「無駄な領域」の定義に依存しますが, 自然なのは #4 の「リスト構造を使う」ですね.
- asuncion
- ベストアンサー率33% (2127/6289)
リスト構造でも使ってみたらどうでしょう。
- tatsu99
- ベストアンサー率52% (391/751)
#1です。 以下訂正します。 (3)2002行を読み込んだとき を (3)2001行を読み込んだとき に訂正します。
- tatsu99
- ベストアンサー率52% (391/751)
非常にいい質問ですね。 この問題は、専門家でも、問題となる重要な問題です。 対策案としては、2案が考えられます。 1案: 予め、起動パラメータで、ファイルのサイズの最大行を与えておく。その行数分データを格納できるの領域のみ、mallocし、それを越えた場合は、エラーメッセージをだして、ギブアップする。 (ギブアップした場合は、次に起動パラメータの値を大きくして再度起動すればよい。) 2案: 最初はmallocしません。その代わり、バッファに格納できない場合、バッファをmallocします。その場合、例えば1000行分単位で拡張するとします。 (1)最初はないので、1行読み込んだときに、バッファを1000行分確保する。 (2)1001行を読み込んだとき、今までのバッファサイズ+1000行分のバッファを確保し、そこへ今までのバッファの内容をコピーする。 そして、今までのバッファを解放する。 (3)2002行を読み込んだとき、(2)と同様の処理を行う。 以下同様。もちろん、その都度、mallocの戻り値はチェックして、メモリ確保エラーの場合は、ギブアップします。