• ベストアンサー

条件によって構造体のリスト構造を変えたい

こんにちは。 C(C++)で構造体を使っているのですが、まだまだ未熟で使い方が良く分かりません。以下のことを実施したいのですが、やり方をどなたかご教授頂けませんでしょうか。よろしくお願いします。 条件によって構造体のリスト構造を変えたいのです。 例えば、 条件1の場合は 構造体a→構造体b 条件2の場合は、 構造体a→構造体c 上記のようにです。そして構造体のルートから参照先をたどっていくことで、配下の構造体の値を取得したいのです。 文法上許されないようですが、イメージとしては、 struct a aa; aa.c->b.aa ということをしたいのです。よろしくお願いします。 struct a{ char a; char b; struct c; : }; struct b{ char aa; : }; struct c{ : : };

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

一番手っ取り早いのは、構造体aの中に、構造体bと構造体cの両方のポインタを持たせておいて、使わない側にはNULLを入れるといった方法でしょうか。 struct a {  /* .bまたは.cのNULLではない方が有効 */  struct b *b;  struct c *c; }; 他には、構造体aと構造体bの最初のフィールドの型を同じにしておいて、そこにaかbかを判別できる値を格納するようにし、構造体aと構造体bの共用体へのポインタを構造体aに持たせるといった方法です。 struct b {  char tag; /* 'b'を格納 */  ... }; struct c {  char tag; /* 'c'を格納 */  ... }; struct a {  union  {   struct b;   struct c;  } *p; /* .p->b.tagが'b'なら構造体b, 'c'なら構造体c */ }; 好みかもしれませんが、私なら多分前者を使います。

kerberos_001
質問者

お礼

ご回答ありがとうございます。 返信が遅くなり申し訳ありません。 どうもありがとうございました。

その他の回答 (3)

  • ency
  • ベストアンサー率39% (93/238)
回答No.4

No2 jacta さん、No3 Tacosan さんが回答されているやり方が、おそらくわかりやすい方法でしょうけど、もうちょっと汎用的にしてみました。 # 汎用ポインタ (void*) とキャストの嵐なので、マクロを使うことに # しました。 ------------------------------------------------ /* 判定用 ENUM 値 */ enum tag_e { A_STRUCT, B_STRUCT, C_STRUCT }; /* 構造体の定義 */ struct link_s { enum tag_e tag; void *link_ptr; }; struct a_s { struct link_s link; char aa; }; struct b_s { struct link_s link; char bb; }; struct c_s { struct link_s link; char cc; }; /* 変数定義 */ struct a_s a = { A_STRUCT }; struct b_s b = { B_STRUCT }; struct c_s c = { C_STRUCT }; /* s->t のリンクを参照するためのマクロ */ #define link( s, t ) ((struct t##_s*)(s.link.link_ptr)) /* s からリンクしている先の構造体を判定するためのマクロ */ #define link_tag( s ) (((struct link_s*)(s.link.link_ptr))->tag) ------------------------------------------------ たとえば、次のようにすることになります。 ------------------------------------------------ /* 構造体の値設定およびリンク処理 */ a.aa = 'A'; if ( 条件1 ) { b.bb = 'B'; link( a, b ) = &b; } else if ( 条件2 ) { c.cc = 'C'; link( a, c ) = &c; } /* リンク先構造体の確認 */ if ( link_tag( a ) == B_STRUCT ) { printf( "a->b.bb=%c\n", link( a, b )->bb ); } else if ( link_tag( a ) == C_STRUCT ) { printf( "a->c.cc=%c\n", link( a, c )->cc ); } ------------------------------------------------ これでうまくいく理由は、ちょっと考えてみてください。 # わからないまま使うと、あとでメンテナンスとかをするときに # 大変なことになると思いますので。。。

kerberos_001
質問者

お礼

ご回答ありがとうございます。 返信が遅くなり申し訳ありません。 どうもありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

#2 とほぼ同じですが, 自分の好みだと struct a { enum { as_b, as_c } tag; union { struct b *b; struct c *c; }; }; くらいですかね.

kerberos_001
質問者

お礼

ご回答ありがとうございます。 返信が遅くなり申し訳ありません。 どうもありがとうございました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

何がやりたいのか、いまいち分かりません。 条件というのは、構造体の中に持っているのでしょうか? 構造体bや構造体cから先のつながり方も分かりません。

kerberos_001
質問者

補足

ご回答ありがとうございます。 説明不足で申し訳ありません。 やりたいことは、構造体のメンバ変数の中に、 別の構造体のポインタを設定したいです。 >条件というのは、構造体の中に持っているのでしょうか? 構造体の外で条件判定しています。例えば、 <処理開始>  構造体aへの値の設定 if 条件1の場合  構造体bへ値の設定  (構造体aと構造体bにリンクを貼りたいので   構造体aのメンバ変数に構造体bのポインタを   設定したい) else if 条件2の場合  構造体cへの値の設定  (構造体aと構造体cにリンクを貼りたいので   構造体aのメンバ変数に構造体cのポインタを   設定したい) <構造体から値を取り出す> ・まず無条件に値が設定されている構造体aの値を取り出す。 ・次の値を取り出したいが、値は構造体bと構造体cのどちらに入っているか分からない。  そこで構造体aのメンバ変数の参照先から値を取り出す。  構造体bと構造体cのメンバ変数はそれぞれ異なっているため、設定処理と取り出し処理も条件によって異なります。 ※条件1と条件2の判定結果を、構造体ではなく、例えばグローバル変数などに退避しておいて、<構造体から値を取り出す>処理の中で、参照する構造体をbかcか判定すれば、構造体をリストする必要はないのかもしれませんが… 以上、まだ説明不足かもしれませんが、よろしくお願いいたします。

関連するQ&A