【问题标题】:Generic stack don't push or pop value通用堆栈不推送或弹出值
【发布时间】:2014-10-02 21:37:42
【问题描述】:

我正在尝试在 C 中实现通用堆栈,但我无法打印我推送的值。这是代码

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h>

typedef struct{
    void *elems;
    int sizeOfElems;
    int allocated;
    int lenght;
}stack;

void allocate_stack(stack *s, int sizeOfElements){
    assert(sizeOfElements > 0);
    s->sizeOfElems = sizeOfElements;
    s->allocated = 2;
    s->lenght = 2;
    s->elems = malloc(sizeOfElements * s->allocated);
}

void deallocate_stack(stack *s){
    free(s->elems);
}

void push_elem(stack *s, void *elem){
    s->lenght += 1;
    if(s->allocated == s->lenght){
        realloc(s, s->lenght * s->sizeOfElems);
        s->lenght *= 2;
    }
     void *target = (char *)s->elems + s->lenght * s->sizeOfElems;
     memcpy(target, elem, s->sizeOfElems);
}
void pop_elem(stack *s, void *elemAddr){
    void *source = (char *)s->elems + (s->lenght-1) * s->sizeOfElems;
    memcpy(elemAddr, source, s->sizeOfElems);
    s->lenght -=1;
}
int main(){
    stack s;
    allocate_stack(&s, 1);
    char a = 'a';
    push_elem(&s, &a);
    char *elem = NULL;
    pop_elem(&s, elem);
    printf("%s", elem);
    deallocate_stack(&s);
    return 0;
}

问题是我运行程序时什么都没有,只需按回车键关闭窗口。我正在使用 GCC 工具包在 Linux 上编程。

【问题讨论】:

  • 我仍在扫描您的程序,但我的第一个想法是您没有在 allocate_stack() 函数中检查空 s
  • 我不需要,s在stack中声明,只有elems在heap中。
  • 我的意思是你在main() 中声明stack *s = NULL;(换句话说,s 是一个空指针),然后你将该空指针传递给allocate_stack(),它会立即尝试取消引用该指针。按原样运行您的代码(尽管我同意我使用 Visual Studio 在 W7 上)导致在第一次取消引用发生时,s-&gt;sizeOfElems = sizeOfElements; 行上几乎立即发生程序崩溃。不过,我完全有可能在这里误解了一些东西,所以也许你可以让我直截了当。
  • 另一条评论:我猜你是最近才开始接触 C 语言的,可能来自 Python 世界,因为你在 push_elem() 中的 if 语句可能不会做你想做的事去做。您可能应该将if 语句的整个主体括在{...} 花括号中。
  • 我的编程背景涉及 Python,但这不是我的第一语言,if 语句是错字。这只是一个测试,我的意思是我尝试了 stack *s = NULL,因为仅声明 stack s 不起作用。

标签: c generics


【解决方案1】:

您缺少堆栈结构的分配。当您执行allocate_stack 时,您必须先调用 allocate 来创建堆栈对象,然后再将其分配给它。例如,您传入的 s 是 null 并且您开始尝试将值分配给它的各个字段。这是未定义的行为,可能是您的程序无法运行的原因。

尝试更改 allocate_stack 函数的签名以返回堆栈指针,然后第一步应该是 malloc(sizeof struct stack) 。您应该返回从 malloc 处获得的指针并将其分配给 s。

编辑:除非您希望堆栈位于堆栈上,在这种情况下,您可以像分配普通变量一样分配它。

【讨论】:

  • 我的想法是要在堆栈中分配堆栈而不是在堆中,只有元素(来自结构的一部分)要在堆中分配。但是我在 main func 中修改了 stack 的声明,并在堆中分配了 s,得到了相同的结果。
  • 好吧,你从来没有真正创建过,然后你只是创建了一个指针。要做到这一点,你必须做 stack s;而不是堆栈*s;看到这个问题google.com/…
  • 发生了什么事,说它不起作用并不能帮助任何人帮助你。社区不是来为​​你写代码的,至少给出一个错误信息。
  • 我没有收到任何错误消息,我只从 xterm 中得到“按 .... 返回”,我的调试器坏了(不知道为什么)。我使用 QT creator 作为 IDE 和 gcc 工具包,我在 debain wheezy x86 上运行。
  • 尝试使用新代码更新您的原始问题
【解决方案2】:

在你的 push_elem 中:

    s->lenght += 1;
    if(s->allocated == s->lenght){
        realloc(s, s->lenght * s->sizeOfElems);
        s->lenght *= 2;
    }

如果空间用完,您似乎正在尝试重新分配空间,但您分配的默认值 2 将保持不变,您可能应该执行以下操作:

    if (s->allocated < s->lenght) {
        realloc(s->elems, ....)
        //Increase both allocated and length to represent the current state of the stack
    }

请注意,在 realloc() 调用中,您传递的是堆栈中的 s,这不会满足您的要求: http://pubs.opengroup.org/onlinepubs/7908799/xsh/realloc.html 根据您的结构,您应该通过 s->元素

另外,在调用 pop_elem 之前,您将 NULL 分配给 elem。在您的 pop_elem 中,这是您尝试执行 memcpy() 的地方。为此,您必须分配内存:http://pubs.opengroup.org/onlinepubs/009695399/functions/memcpy.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 2020-12-19
    • 2020-02-06
    • 2021-07-15
    • 1970-01-01
    • 2018-06-12
    相关资源
    最近更新 更多