C语言中的通用堆栈

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 函数中返回/获取弹出的值?我不想改变实现方式,但如果有一种好的方法可以尽可能地保持实现方式相同,那么我会很感激。其他方法也是可以接受的。


void* 的意义在于指向的内存实际类型未指定。如果您的堆栈包含 int,则执行以下操作:int i; stackPop(s, &i); - i 将接收该值。 - asveikau
@asveikau:现在可以了吗?我添加了一个assert语句。谢谢:D - Vaibhav Agarwal
@nneonneo 我正在实现自己的通用堆栈代码。如果我使用别人的代码,那么我就不会有任何关于它的知识!! - Vaibhav Agarwal
好的,你是在使用自己定义的接口还是别人的接口? - nneonneo
我在一些评论中看到你提到这是你个人实现的堆栈,但我在斯坦福大学的一些讲座中看到了完全相同的代码。你显然是复制粘贴的。 - Martin Chekurov
显示剩余16条评论
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;
}

请注意,调用者仍需提供内存和地址以弹出数据;如果您希望避免这种情况,可以通过函数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()释放它,并增加了需要处理内存不足情况的小复杂性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接