4

C でジェネリック スタックを実装していますが、stackPop メソッドで問題に直面しています。私の構造は次のとおりです。

「Stack.h」ファイル

        typedef struct{
            void *elems;
            int elemSize;
            int allocLength;
            int logLength;
            void (*freefnc)(void *);
        } Stack;

    void stackNew(Stack *s, int elemSize, void (*freefnc)(void *));
    void stackDispose(Stack *s);
    void stackPush(Stack *s, void *elemAddr);
    void stackPop(Stack *s, void *target);

Stack.c

    #inlcude<Stack.h>

    void stackNew(Stack *s, int elemSize, void (*freefnc)(void *)){
        s.allocLength = 4;
        s.logLength = 0;
        s.elemSize = elemSize;
        s.elems = malloc(4*elemSize);
        s.freefnc =  freefnc;
    }

    void stackDispose(Stack *s){
        if(s.freefnc!=NULL){
            for(int i=0; i<s.logLength; i++){
                freefnc((char *)s.elems+i*s->elemSize);
            }
        }
        free(s.elems);
    }

    void Stringfree(void *elem){
        free(*(char**)elem);
    }

    void stackPush(Stack *s, void *elemAddr){
        if(s.alloclength == s.logLength){
            stackGrow(s);
        }
        void *target = (char *)s.elems + s.logLength*s.elemSize;
        memcpy(target,elemAddr,s.elemSize);
        s.logLength++;
    }

    static void stackGrow(Stack *s){
        s.allocLength*=2;
        s.elems = realloc(s.elems, s.alloclength*s.elemSize);
        assert(s.elems!=NULL);
    }

    void stackPop(Stack *s, void *elemAddr){
        void *source = (char *)s.elems + (s.logLength-1)*s.elemSize;
        memcpy(elemAddr,source,s.elemSize);
        s.logLength--;
    }

stackPop関数でポップされた値を返す/取得するにはどうすればよいですか? 実装を変更したくはありませんが、実装を可能な限り同じに保つ良い方法があれば、それをいただければ幸いです。他のアプローチも受け入れられます。

4

1 に答える 1

6

あなたができる最善のことは、ポップされたデータへのポインターを返すことだと思います(void*「ジェネリック」関数に対してCでできる最善の方法であるため):

void* stackPop(Stack *s, void *elemAddr){
        void *source = (char *)s.elems + (s.logLength-1)*s.elemSize;
        memcpy(elemAddr,source,s.elemSize);
        s.logLength--;
        return elemAddr;
}

呼び出し元は、データをポップするメモリとアドレスを提供する必要があることに注意してください。ed が必要な場合は、関数malloc()にメモリを持たせることでそれを回避できます。

void* stackPop(Stack *s){
        void *source = (char *)s.elems + (s.logLength-1)*s.elemSize;
        void *elemAddr = malloc(s.elemSize);
        // if (!elemAddr) handle_error();
        memcpy(elemAddr,source,s.elemSize);
        s.logLength--;
        return elemAddr;
}

もちろん、不要にfree()なったときに呼び出し元が必要になり、メモリ不足の状況を処理する必要があるという小さな複雑さが追加されます。

于 2012-09-27T06:37:37.990 に答える