動的な構造体について

[戻る]
クリリン 2002/02/13(水) 17:39:01
どうも、クリリンです。
早速ですが、質問させてください。
ファイルから約100〜1000件ぐらい入っているレコードの情報を、それぞれのデータごと
に格納するには、構造体を使うのが最も有効的だと判断しているのですが、レコード数がファイ
ルによって未知数の為、動的な構造体を定義しないといけないと思っております。
その為には、どのように記述したらよろしいのでしょうか?
どうか、みなさんの知恵をお貸しください。
よろしくお願いします。

NGA 2002/02/13(水) 19:04:20
質問です。
1レコードを格納する構造体そのものが動的なのか?
それとも複数レコードを格納したいがレコード数が未知数な為、
構造体配列の配列数が動的なのか?
どちらでしょうか?

クリリン 2002/02/13(水) 22:18:40
どうも、クリリンです。
NGA さん、ありがとうございます。
質問があいまいですいません。
1レコードを格納する構造体自体は動的ではなく、
単に、レコードの数が未知数な為、構造体配列を動的にしたいのです。
どうか宜しくお願いします。

sugar 2002/02/13(水) 22:55:59
「配列」にこだわるなら、malloc()やGlobalAlloc()などで任意の件数分のメモリを確保し、
足りなくなったら再確保...という感じでしょうか。
あまりよろしいやり方ではありませんけどね。

「配列」である必要がなければ、自己参照構造体にしてリスト構造にするとか。
MFCでもよければ、CArrayを使うとか。

NGA 2002/02/14(木) 09:04:04
質問です。
ファイル上における1レコードのサイズは固定長ですか?
それとも可変長ですか?

クリリン 2002/02/14(木) 09:32:08
みなさん、ご回答ありがとうございます。
ファイル上における1レコードのサイズは固定長です。

NGA 2002/02/14(木) 09:42:45
>ファイル上における1レコードのサイズは固定長です。

ファイルサイズからレコード数が計算できますよね?
格納するだけなら、構造体配列を動的に確保するのが簡単かと思います。

[E-Mail] 2002/02/14(木) 10:36:44
自分がよくやるやり方としては、

typedef struct
{
    CString a       ;
    CString b       ;
    CString c       ;
}aaa_t ;

CArray<aaa_t,aaa_t> m_aaaArray ;

こんな感じです。
他の方々の回答といってることは同じですが、ご参考ってことで。

クリリン 2002/02/14(木) 13:30:26
とりあえず、ん さんのやり方を試してみたいと思います。
ところで、双方向リストを思いついたのですが、これを使用した場合、[qsort]は難しいのでし
ょうか?また、構造体内に連番用の変数を入れており、ソート終了後に連番を振りなおしたいの
ですが、やはり、双方向リストでは、処理が遅くなってしまうのでしょうか?
結論的には、固定長ファイルのデータ取得および追加、削除、更新、参照はどの方法が一番適切
なのか教えていただけないでしょうか?
よろしくお願いします。

NGA 2002/02/14(木) 13:41:31
>結論的には、固定長ファイルのデータ取得および追加、削除、更新、参照はどの方法が一番適>なのか教えていただけないでしょうか?

ファイルサイズが固定長ならただの動的配列でもよいと思いますが、
そうでないならリスト構造にするのが無難な気がします。

>ところで、双方向リストを思いついたのですが、これを使用した場合、[qsort]は難しいので>ょうか?

配列でないと……。

クリリン 2002/02/14(木) 13:50:30
NGA さん、いつも回答くださいまして、ありがとうございます。
やはり、双方向リストはバブルソートしかできないのでしょうか?
でも、qsortの理屈は、ポインタの入れ替えですよね?
だったら、双方向リストのqsort版を作るのでは駄目ですか?
っていうか、そうゆうのは無いのですか?
色々と質問してすいません。

NGA 2002/02/14(木) 14:18:01
>でも、qsortの理屈は、ポインタの入れ替えですよね?

ポインタの入替ではなく、要素そのものの入替です。

>クイックソートでは(昇順ソートの場合)、まず適当な値Xを選ぶ。
>その時、配列のX以下の要素数とX以上の要素の数とはなるべく同じになるようにする。
>X以下の要素を配列の前半に、X以上の要素を配列の後半に集める。
>配列の前半が要素数が2以上なら、配列の前半を再帰的にクイックソートする。
>配列の後半が要素数が2以上なら、配列の後半を再帰的にクイックソートする。
>このように配列を次々に2つにして、それぞれについてソートを行う。

だそうです。

クリリン 2002/02/14(木) 14:27:37
>ポインタの入替ではなく、要素そのものの入替です。
あ、すいません。勘違いしてました。

NGA 2002/02/14(木) 14:39:56
リストポインタの配列を作り、ポインタで参照してソートをする
クイックソートを作るというのはどうでしょう?

クリリン 2002/02/14(木) 15:30:33
>リストポインタの配列を作り、ポインタで参照してソートをする
>クイックソートを作るというのはどうでしょう?
そうです。そのことを言いたかったのですが・・・

NGA 2002/02/14(木) 15:34:20
では、作るということで解決ですか?

クリリン 2002/02/14(木) 15:55:40
ただ、
typedef struct
{
    CString a       ;
    CString b       ;
    CString c       ;
}aaa_t ;

CArray<aaa_t,aaa_t> m_aaaArray ;
の使い方がよく判らなくて・・・
現在、試行錯誤中です。

NGA 2002/02/14(木) 15:57:42
では、頑張ってくださいということで。

クリリン 2002/02/14(木) 16:02:09
[[解決]]
とりあえず、解決としておきます。
ちなみに、「STL」を使うと、データをDBみたいに使えるのですね・・・
どちらも、やってみます。
みなさん、ありがとうございました。

クラフトマン 2002/02/15(金) 22:29:41
解決しているのに書き込むのもなんですが、自前の双方向リストで、自前の
クイックソートを書きたい方のために補足しておきます。
双方向リストで、クイックソートを実装するのは、割と簡単だと思います。
リストは、データの移動が、ポインタ操作だけで出来るので、その点では、
クイックソートと相性がいいともいえます。

簡単に手順を書きます。
1.ソート範囲先頭ノードのデータを分割値とする。
2.範囲末尾になるまで、1つずつノードのデータを分割値と比較し、小さけ
  れば、そのノードを分割地ノードの前に移動する。
ここまでの処理で、分割値ノードを挟んで、前にあるのが小さいデータ、
後にあるのが大きいデータとなっていることになります。
これを再帰的に、前半、後半それぞれの範囲で行えば、ソートできます。

注意事項は、配列のクイックソートと同様です。
より実用性を高めるには、ソート済みデータに対するソートの対応(分割値
の決め方等)とか、ソート範囲が小さくなった場合のアルゴリズムの切り替
えとか、再帰のネスト数を減らす工夫とかを考える必要があるでしょう。

#このところ、忙しすぎて、書き込みも久しぶり。今夜も徹夜か? :<

クラフトマン 2002/02/15(金) 22:44:44
一部訂正。

誤
ここまでの処理で、分割値ノードを挟んで、前にあるのが小さいデータ、
後にあるのが大きいデータとなっていることになります。

正
ここまでの処理で、分割値ノードを挟んで、前にあるのが小さいデータ、
後にあるのが、大きいか等しいデータとなっていることになります。

また、このロジックに従えば、クイックソートなのに、安定なソート
(同じ値のデータの順序が保たれるソート)が実現できます。

古いスレッドには追加発言できません。