【问题标题】:Trouble with pointers and stack implementation [closed]指针和堆栈实现的问题[关闭]
【发布时间】:2016-10-04 05:09:12
【问题描述】:

我正在尝试创建一个在 C 中实现堆栈的程序。

目前,我的堆栈显示为空。

我认为这是因为我传递了堆栈而不是指向堆栈的指针。

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

typedef struct node
{
    int info;
    struct node * ptr;
}node;

//create
//push
//pop
//destroy
//display
void push(int, node * top_node);
void pop(node * top_node);
void destroy(node * top_node);
void display(node * top_node);
int main(int argc, char** argv) 
{
    node * top_node = NULL;

    push(1, top_node);
    push(5, top_node);
    push(55, top_node);
    display(top_node);
    pop(top_node);
    display(top_node);
    pop(top_node);
    display(top_node);
    pop(top_node);
    display(top_node);
    push(1, top_node);
    display(top_node);
    destroy(top_node);
    return (EXIT_SUCCESS);
}

void display(node * top_node)
{
    node * temp = top_node;
    if(top_node == NULL)
    {
        printf("The stack is empty\n");
        return;
    }
    while(temp != NULL)
    {
        printf("%d\n ", temp-> info);
        temp = top_node -> ptr;
    }
}

void push(int data, node * top_node)
{
    if(top_node == NULL)
    {
        top_node = (struct node **) malloc(1*sizeof(struct node));
        top_node ->ptr = NULL;
        top_node -> info = data;         
    }
    else
    {
        node * temp = (struct node *) malloc(1*sizeof(struct node));
        temp -> ptr = top_node;
        temp -> info = data;
        top_node = &temp;
    }  
}

void pop(node * top_node)
{
    node * new_top = top_node;
    if(new_top == NULL)
    {
        printf("\nERROR, the stack is empty");
        return;
    }
    else
    {
        new_top = new_top -> ptr;
        printf("popped value = %d", top_node -> info);
        free(top_node);
        top_node = new_top;
    }
}

void destroy(node * top_node)
{
    node * temp = top_node;
    while(temp != NULL)
    {
        temp = top_node -> ptr;
        free(top_node);
        top_node = temp;
        temp = temp->ptr;   
    }
    free(temp);
}

我得到的输出是这样的:

堆栈为空
ERROR,堆栈为空堆栈为空
ERROR,堆栈为空堆栈为空
ERROR,堆栈为空堆栈为空
堆栈为空

运行成功(总时间:227ms)

我认为我应该传递一个指向堆栈的指针,我尝试实现它但它抛出了一堆错误。

如果没有给我完整的答案,我们将不胜感激。

【问题讨论】:

  • 什么是1 * sizeof ...????并且不要投射malloc()
  • 打开编译器警告,并修复它们。你有一些指针类型不匹配,这是不好的。
  • "RUN SUCCESSFUL (total time: 227ms)" - 根据您的输出,您的代码是正确的。够奇怪的。
  • 查看我的回答,除了其他回答者发现的问题。
  • 为什么我被否决了?我是这个网站的新手,到目前为止它似乎对新用户不太友好。

标签: c pointers stack


【解决方案1】:

push() 中分配给top_node 无效,因为该指针是在本地声明的,并且仅存在于push() 函数本身的堆栈帧中。相反,您可以将指针传递给main() 函数中声明的指针,如下所示

void 
push(int data, node **top_node)
{
    if (*top_node == NULL)
    {
        *top_node = malloc(sizeof(**top_node));
        if (*top_node == NULL)
            return; // maybe warn about the error or abort the whole program
        (*top_node)->ptr = NULL;
        (*top_node)->info = data;
    }    
    else
    // append the node       
}

否则,分配的空间将永远丢失,导致内存泄漏,因为当函数返回时,持有它的 adderss 的指针被破坏。

【讨论】:

  • 这是我一直在寻找的解决方案。我曾经有过这个,但在分配指针和数据时,我无法让它将 top_node 识别为结构。我认为那是因为我遗漏了括号。
  • @thutchi 更准确地说,operator precedence.
  • 好的,谢谢。我想我明白现在发生了什么。第一次做堆栈,距离链表已经好几年了。谢谢。
  • 伟大的工作是第一个确定主要问题的人。
【解决方案2】:

除了问题之外,关于 iharobCherubim Anand 都确定的对top_node按值调用,还有其他还有问题:

  • 所有必须修改top_node 的函数都必须使用node ** 传入其地址,display 除外,因为它只读取top_node 而无需修改它。
  • 对此类修改函数的调用必须传入top_node 的地址,使用&amp; 运算符,如pop(&amp;top_node);,而不是像display 函数如display(top_node); 那样传递其值.
  • 在此类函数中使用top_node 必须使用* 运算符(如*top_node)使用一级取消引用,display 除外,其中仅传递值。
  • display 函数中,temp = top_node -&gt; ptr; 行将始终将temp 设置为第二个元素,从而导致循环永远迭代。应该改为temp = temp-&gt;ptr;
  • push 中的 (struct node **) malloc(1*sizeof(struct node)); 不正确,应更改为 (struct node*)malloc(sizeof(struct node));。任何数字乘以1 都保持不变。
  • destroy 函数中的最后两个语句是错误的,必须删除以保留正确的功能。

这里是修改后的代码:

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

typedef struct node
{
    int info;
    struct node *ptr;
}node;

//create
//push
//pop
//destroy
//display
void push(int, node ** top_node);
void pop(node ** top_node);
void destroy(node ** top_node);
void display(node * top_node);
int main(int argc, char** argv) 
{
    node *top_node = NULL;

    push(1, &top_node);
    push(5, &top_node);
    push(55, &top_node);
    display(top_node);
    pop(&top_node);
    display(top_node);
    pop(&top_node);
    display(top_node);
    pop(&top_node);
    display(top_node);
    push(1, &top_node);
    display(top_node);
    destroy(&top_node);
    return (EXIT_SUCCESS);
}

void display(node * top_node)
{
    node * temp = top_node;
    if(top_node == NULL)
    {
        printf("The stack is empty\n");
        return;
    }
    while(temp != NULL)
    {
        printf("%d\n", temp->info);
        temp = temp->ptr;
    }
}

void push(int data, node ** top_node)
{
    if(top_node == NULL)
    {
        *top_node =  (struct node*)malloc(sizeof(struct node));
        (*top_node)->ptr = NULL;
        (*top_node)-> info = data;
    }
    else
    {
        node * temp = (struct node*)malloc(sizeof(struct node));
        temp -> ptr = *top_node;
        temp -> info = data;
        *top_node = temp;
    }
}

void pop(node ** top_node)
{
    node * new_top = *top_node;
    if(new_top == NULL)
    {
        printf("ERROR, the stack is empty\n");
        return;
    }
    else
    {
        new_top = new_top -> ptr;
        printf("Popped value = %d\n", (*top_node)-> info);
        free(*top_node);
        *top_node = new_top;
    }
}

void destroy(node ** top_node)
{
    node * temp = *top_node;
    while(temp != NULL)
    {
        temp = (*top_node)-> ptr;
        free(*top_node);
        *top_node = temp;
    }
}

【讨论】:

  • c中没有引用传递这种东西。
  • 谢谢,这与其他人所说的一致。应该投malloc() 吗?那里似乎有差异。我认为destroy() 函数很有意义。如果您总是检查 temp 是否等于 NULL,那么您正在查看堆栈中的下一个对象。正确的?因此,您总是释放高于温度的项目。这是错误的思考方式吗?
  • @thutchi 如果你投malloc(),你会冒很大的风险。 Read here for more information。此外,您不能在c 中通过引用传递变量,您可以做的是传递一个指向存储数据的内存位置的指针,这是非常不同的。您需要取消引用指针来更改它,而您不需要对作为引用的变量执行任何特殊操作。值得注意的是,c++ 已通过引用传递,因此混合这些概念可能会成为问题。
  • @iharob 现在说得通了。在学校里,我们被教导铸造。诡异的。当@Ahmed Akhtar 在destroy() 函数中释放top_node 时,我确实还有一个问题free(temp) 我通过内存泄漏检查器运行了这个,它按照他写的方式工作。那么,我们为什么不用free(temp)
  • @thutchi 销毁函数基本上在temp 中存储下一个元素一段时间,然后frees 上一个元素,然后将top_node 重置为先前存储在temp 中的下一个元素.这样所有内存都被释放了,没有释放temp的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
  • 2020-01-03
  • 1970-01-01
  • 2013-04-28
  • 2014-12-18
  • 1970-01-01
  • 2015-08-05
相关资源
最近更新 更多