アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんにちは。

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{
:
:
};

A 回答 (4件)

一番手っ取り早いのは、構造体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 */
};

好みかもしれませんが、私なら多分前者を使います。
    • good
    • 0
この回答へのお礼

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

どうもありがとうございました。

お礼日時:2005/05/02 12:46

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 );
}

------------------------------------------------

これでうまくいく理由は、ちょっと考えてみてください。
# わからないまま使うと、あとでメンテナンスとかをするときに
# 大変なことになると思いますので。。。
    • good
    • 0
この回答へのお礼

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

どうもありがとうございました。

お礼日時:2005/05/02 12:47

#2 とほぼ同じですが, 自分の好みだと


struct a {
enum { as_b, as_c } tag;
union {
struct b *b;
struct c *c;
};
};
くらいですかね.
    • good
    • 0
この回答へのお礼

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

どうもありがとうございました。

お礼日時:2005/05/02 12:46

何がやりたいのか、いまいち分かりません。



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

この回答への補足

ご回答ありがとうございます。

説明不足で申し訳ありません。
やりたいことは、構造体のメンバ変数の中に、
別の構造体のポインタを設定したいです。

>条件というのは、構造体の中に持っているのでしょうか?
構造体の外で条件判定しています。例えば、

<処理開始>
 構造体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か判定すれば、構造体をリストする必要はないのかもしれませんが…

以上、まだ説明不足かもしれませんが、よろしくお願いいたします。

補足日時:2005/04/21 14:43
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!