0

次の関数は、更新されたポインターをinsertSNode挿入itemしてs します。return関数内ではinsertSnode、異なるデータからの各データstructが適宜逆参照されます。

問題: (LINE 1)、(LINE 2)、(LINE 3)、(LINE 4)で コンパイラ エラーが発生し、次のエラー メッセージが表示されます。

「メンバー参照ベース タイプ 'void' は構造体または共用体ではありません。」

質問:

コンパイラ エラーを取り除くにはどうすればよいですか? 私ができない場合、代わりに、この状況と同じくらい関数を書くことで、より良い解決策がありますか? 型が多すぎるとしましょうstruct(つまり、Type_A、Type_B など)。異なる型宣言で異なる関数を作成するのは非常に非効率的です。

*pListTypeA = (Type_A *) insertSnode(*pListTypeA, pPreTypeA, pTypeAItem, TYPEA);
*pListTypeB = (Type_B *) insertSnode(*pListTypeB, pPreTypeB, pTypeBItem, TYPEB);
*pListTypeC = (Type_C *) insertSnode(*pListTypeC, pPreTypeC, pTypeCItem, TYPEC);
// more assignments

insertSnode意味:

void* insertSnode(void* pList, void* pPre, char* item, const int type) {
    void *pNew;

    if (TYPEA == type) {
        pList = (Type_A*) pList;
        pPre =  (Type_A*) pPre;
        pNew =  (Type_A*) pNew;
    } else if (TYPEB == type) {
        pList = (Type_B*) pList;
        pPre =  (Type_B*) pPre;
        pNew =  (Type_B*) pNew;
    } else (TYPEC == type) {
        pList = (Type_C*) pList;
        pPre =  (Type_C*) pPre;
        pNew =  (Type_C*) pNew;
    }
    if (!(pNew = malloc(sizeof(*pList)))) {
        printf(ERR_NOT_ENOUGH_MEMORY);
        exit(EXIT_NOT_ENOUGH_MEMORY);
    }
    pNew->name = item;    // compiler error: (LINE 1)
    if (pPre == NULL) {
        pNew->link = pList;    // compiler error: (LINE 2)
        pList = pNew;
    } else {
        pNew->link = pPre->link;    // compiler error: (LINE 3)
        pPre->link = pNew;    // compiler error: (LINE 4)
    }
    return pList;
}

ノート:

参考までに: このコードは、型宣言に if ステートメントを使用せず、1 つの型 (Type_A など) だけで実行できました。したがって、型宣言以外に外部の問題がないことは誰もが知っています。

4

3 に答える 3

1

ここでの問題は、以下の行です

pList = (TYPE_A*) pList;

引き続きポインターに代入するvoid*ため、キャストは役に立たず、コードの残りの部分はそれが起こらなかったかのように動作します。

これをきれいに修正する方法がわかりません。申し訳ありません。中間を提案するつもりでしたstructが、インスタンスを直接変更したいのでうまくいきません。

これがあればC++、ジェネリックが答えだったでしょう..

現在のアイデアを機能させるには、型ごとに異なる変数を作成してそれらにキャストするか、変数を使用するたびにキャストする必要があります。

または、Michael Pryor が示唆するように、型を 1 つに統一してみてください。

それ以外の場合は、マクロを試すことができます。上記のコードの 1 行の実装については、以下の例を参照してください。

#define OPERATEONTYPE(Type,TypeEnum)\
if(type == TypeEnum) {\
    ((Type*)pNew)->name = item;\
}


void* insertSnode(void* pList, void* pPre, char* item, const int type) {
         OPERATEONTYPE(Type_A,TYPEA)
    else OPERATEONTYPE(Type_B,TYPEB)
    else ....
}

#undef OPERATEONTYPE //should only be used/usable within that function anyway
于 2013-02-17T03:07:31.853 に答える
1

すべての「構造体型」に共通の値 (name、next、prev など) がある場合、共用体を使用したいのではないでしょうか? 共通部分を汎用構造体に格納してから、共用体を使用して非共通部分を格納します。

@KarthikTの答えは正しいことに注意してください.pNewは常にvoid型であり、それに関連付けられた「構造体」がないため、これらは実際には構文エラーです.pNew->nameは無意味な構造です.

于 2013-02-17T03:20:40.970 に答える
-2

Karthik が言ったように、でジェネリックを使用する必要がありますc++
c には、1 つの解決策があります。if...else if...elseの最初のブロックを削除しinsertSnode()ます。
次のように使用します。

void* insertSnode(void* pList, void* pPre, char* item, const int type) {
void *pNew;
 if (!(pNew = malloc(sizeof(*pList)))) {
    printf(ERR_NOT_ENOUGH_MEMORY);
    exit(EXIT_NOT_ENOUGH_MEMORY);
}
if (TYPEA == type) {
   if(pPre==NULL){
   (Type_A*)pNew->name=item;
   (Type_A*)pNew->link=plist;
   (Type_A*)pList=pNew;
 }else{
    (Type_A*)pNew->link=(Type_A*)pPre->link;
     (Type_A*)pPre->link;
  }
} else if (TYPEB == type) {
    if(pPre==NULL){
   (Type_B*)pNew->name=item;
   (Type_B*)pNew->link=plist;
   (Type_B*)pList=pNew;
 }else{
    (Type_B*)pNew->link=(Type_B*)pPre->link;
     (Type_B*)pPre->link;
  }
} else if(TYPEC == type) {
   if(pPre==NULL){
   (Type_C*)pNew->name=item;
   (Type_C*)pNew->link=plist;
   (Type_C*)pList=pNew;
 }else{
    (Type_C*)pNew->link=(Type_c*)pPre->link;
     (Type_C*)pPre->link;
  }
}


return pList;
}
于 2013-02-17T03:29:12.343 に答える