list型構造体

[戻る]
robo [E-Mail] 2001/02/09(金) 10:48:22
はじめまして。


list型構造体を調べていたのですが教えていただけたら幸いです。


struct A
{
        char a ;
}
struct B
{
        char b ;
}


struct C
{
        struct a *aa
        struct b *bb
}


struct c *cc


上記のような構造体の時にccだけmallocで領域を1個づつ確保したり
ccの中のaaやbbだけを1個領域を確保するやり方教えていただければ
幸いです。
今までVBをやっていて突然VCをやらなければいけなくなり構造体で四苦八苦
しております。

よろしくお願いいたします。

ku 2001/02/09(金) 11:13:05
猫でもわかるプログラミングのC言語編の34章にリストが載ってますね
http://www.kumei.ne.jp/c_lang/
http://www.kumei.ne.jp/c_lang/intro/no_34.htm

ちなみにroboさんがやられていることはリストではなく
構造体Aと構造体Bのポインタ変数をメンバ変数として構造体Cに定義しているだけです

robo 2001/02/09(金) 11:37:08
猫でもわかるをみたのですが、自己参照型を
使用しているために使えませんでした。
構造体が以下のように決まっているために
変更することができません。

ku 2001/02/09(金) 14:09:48
最終的に何ができればいいのか僕には分かりませんでしたので
それらしいのを書いておきます
うまくご質問された方がより良いアドバイスがいただけますよ
とりあえず動的なメモリの確保でよければこんな感じでしょうか
struct A
{
    char a;
};
struct B
{
    char b;
};
struct C
{
    struct A* aa;
    struct B* bb;
};
struct C* cc;

cc = (C*)malloc(sizeof(C));
if (cc != NULL) {
    cc->aa = (A*)malloc(sizeof(A));
    cc->bb = (B*)malloc(sizeof(B));
    if (cc->aa != NULL) {
        free(cc->aa);
    }
    if (cc->bb != NULL) {
        free(cc->bb);
    }
    free(cc);
}

構造体がZと決められていてそれをリストにした場合です
他にはSTLのlistを使用するという手もあります
10個の要素をリストの最後の要素から確保していき
リストの最初の要素から解放します
struct Z
{
    int abc;
};
struct LISTZ
{
    LISTZ* pListZA;
};
LISTZ* pListAlloc = NULL;
LISTZ* pListBefore = NULL;
LISTZ* pListAfter = NULL;
LISTZ* pListFree = NULL;
int n;
for (n = 0; n < 10; n++) {
    if ((pListAlloc = (LISTZ*)malloc(sizeof(LISTZ))) != NULL) {
        pListAlloc->pListZA = pListBefore;
        pListBefore = pListAlloc;
    }
}
pListFree = pListBefore;
while (pListFree != NULL) {
    pListAfter = pListFree->pListZA;
    free(pListFree);
    pListFree = pListAfter;
}
適当に作ってみたのでミスがあったらごめん

robo 2001/02/09(金) 14:59:20
説明がおかしくてすみません。

構造体が宣言されていて領域をいくつ確保するか不明で処理が発生
するたびに領域を確保していくと、言うことをやりたのですが
線形リストのやり方だとわかるのですが、なにぶん構造体の変更
をかけてはいけないと言うことなので困っています。

ku 2001/02/09(金) 15:09:13
僕が書いた構造体Zと構造体LISTZのような関係にしてもだめですか?
他には単に配列を使用する方法もあります
STLのvectorでもできますし簡単です
配列でも良ければ
mallocしたものをreallocして動的領域のサイズを変更することもできます
GlobalAllocしたものをGlobalReAllocするという方法ありますね

robo 2001/02/09(金) 16:04:28
何度もすいません。

struct A
{
    char a;
};
struct B
{
    char b;
};
struct C
{
    struct A* aa;
    struct B* bb;
};
struct C* cc;

ヘッダ自体いじれないないので、上記構造体をもとに作成しなければ
ならず他に新たな構造体を作成することができません。

ファイル内容
00000001,001,001
00000002,,002
00000003,003,003

ファイルから1レコード読込み1フィールド目の区分コードがあればccの領域を確保し
2フィールド目に差分1があればaaの領域を確保し3フィールド目に差分2があればbb
を確保するということなのですが。差分が1及び2が無ければ領域は確保しなしとなります。

ku 2001/02/09(金) 18:32:51
roboさんのせいではありませんがこの構造体は問題解決を複雑にするために
一役買っていると評するほか無いですね
ヘッダを更新できなくてもソースに構造体を定義しても構わないし
新たに別のヘッダを作成しても構わないだろうし
方法はあると思うよ
これはC言語が難しいとかでなくデータ構造を解析したか設計した人が
構造体を作成したときに悪いデータ構造を採用したという結果です


こんな感じでできそうです
他にも条件があるようですからその辺はうまく変更してやってみてください
struct C* cc = NULL;
bool AddVal(C** ppCC, int nCnt, bool fValA, char cSetA, bool fValB, char cSetB)
{
    C* pC = NULL;
    if (nCnt == 1) {
        pC = (C*)malloc(sizeof(C));
    } else {
        pC = (C*)realloc(*ppCC, sizeof(C) * nCnt);
    }
    if (pC != NULL) {
        int nInsPos = nCnt - 1;
        if (fValA != false) {
            pC[nInsPos].aa = (A*)malloc(sizeof(A));
            pC[nInsPos].aa->a = cSetA;
        } else {
            pC[nInsPos].aa = NULL;
        }
        if (fValB != false) {
            pC[nInsPos].bb = (B*)malloc(sizeof(B));
            pC[nInsPos].bb->b = cSetB;
        } else {
            pC[nInsPos].bb = NULL;
        }
        *ppCC = pC;
        return true;
    } else {
        return false;
    }
}
void FreeVal(C* pCC, int nCnt)
{
    int n;
    for (n = 0; n < nCnt; n++) {
        if (pCC[n].aa != NULL) {
            free(pCC[n].aa);
        }
        if (pCC[n].bb != NULL) {
            free(pCC[n].bb);
        }
    }
    free(pCC);
}

{
    AddVal(&cc, 1, true,  'a', false, 'z');
    AddVal(&cc, 2, false, 'b', false, 'y');
    AddVal(&cc, 3, true,  'c', true,  'x');
    AddVal(&cc, 4, false, 'c', true,  'w');
    FreeVal(cc, 4);
    cc = NULL;

robo 2001/02/09(金) 18:47:42
ありがとうございます、やってみます。
自分もlist型でやってはと提案したのですが、通じませんでした。
既に完成している完成物に追加処理で行うからと思って納得した
ようなしないようなままでstartしてしまいました。

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