【问题标题】:Stack by pointers in C working except at stack underflow在 C 中按指针堆栈,堆栈下溢除外
【发布时间】:2013-07-31 06:31:26
【问题描述】:

我使用指针实现了堆栈。它正在编译和工作,但当堆栈为空时它不会下溢。它给了我一些垃圾价值。我认为问题出在create_stack 函数中。无论从堆栈中弹出多少数据,我都不会收到段错误,这很奇怪。

谁能帮忙?

这是我通过指针对堆栈的完整实现。

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

enum action {PUSH = 1, POP, TOP, QUIT};

typedef struct node
{
    int data;
    struct node *lower;

}stack_node;

void clear_screen(void)
{
    system("cls");
}

static enum action get_user_action(void)
{
    int choice = 0;
    do
    {
        clear_screen();
        printf("%d Push data\n"
               "%d Pop Data\n"
               "%d See the top of the stack\n"
               "%d Exit\n\n"
               "Enter your choice -> ", PUSH, POP, TOP, QUIT);
        scanf("%d", &choice);
    } while (choice != PUSH && choice != POP && choice != TOP && choice != QUIT);
    return (enum action) choice;
}

void create_stack(stack_node **top, int *status)
{
    *top = malloc(sizeof(stack_node));

    *status = PUSH - 1;
    if (*top == NULL){
        *status = PUSH;
    }
}

void push(stack_node **top_stack, int *status, int data)
{
    *status = PUSH - 1;
    stack_node *node = malloc(sizeof(node));
    if (node == NULL)
    {
        *status = PUSH;
        return;
    }

    node -> data = data;
    if (*top_stack == NULL){
        node -> lower = NULL;
    }
    else{
        node -> lower = *top_stack;
    }
    *top_stack = node;
}

int pop(stack_node **top_stack, int *status)
{
    *status = PUSH - 1;
    if (*top_stack == NULL){
        *status = POP;
        return -1;
    }

    stack_node *node = *top_stack;
    int data = node -> data;
    *top_stack = node -> lower;
    free(node);

    return data;
}

int see_top(stack_node **top_stack, int *status)
{
    *status = PUSH - 1;
    if (*top_stack == NULL){
        *status = POP;
        return -1;
    }

    return (*top_stack) -> data;
}

int main(void)
{
    enum action choice;
    int status;

    stack_node *top = NULL;
    create_stack(&top, &status);

    if (status == PUSH)
    {
        printf("Not enough memory\n");
        return 1;
    }

    while ((choice = get_user_action()) != QUIT)
    {
        clear_screen();
        int data;
        switch (choice)
        {
        case PUSH:
            printf("Enter data to be pushed -> ");
            scanf("%d", &data);
            push(&top, &status, data);
            if (status == PUSH){
                printf("Not enough memory\n");
            }
            break;
        case POP:
            data = pop(&top, &status);
            if (status == POP){
                printf("Stack underflow\n");
            }
            else{
                printf("The data is %d\n", data);
            }
            break;
        case TOP:
            data = see_top(&top, &status);
            switch (status)
            {
            case POP:
                printf("Nothing in the stack\n");
                break;
            default:
                printf("The data at top is %d\n", data);
            }
            break;
        default:
            assert(!"You should not have reached this.");
        }
        getchar();
        getchar();
    }
}

【问题讨论】:

  • 为什么函数创建分配内存?
  • @GrijeshChauhan 因为我想做一个可重用的堆栈实现。我使用pointer to pointer to struct 来注意函数中分配的内存不会泄漏。分配的内存放在堆栈上。但正如我所说,我认真地认为这个函数有错误。它似乎在盯着我的脸,但我就是想不出来它是什么。
  • 分配导致返回垃圾值,在随后的弹出操作之后,这可能是未定义行为的原因。
  • @GrijeshChauhan 这真是一个愚蠢的错误。谢谢,问题解决了。
  • 是的,我认为其他一切都是正确的。

标签: c pointers stack underflow stackunderflow


【解决方案1】:

当您创建堆栈时,您会为一个节点分配空间——并且不要用任何东西填充它。因此,在调用 create_stack() 之后,您的堆栈上已经有了一个空白节点。我猜你不想那样,只是这样做

void create_stack(stack_node **top, int *status)
{
   *top = NULL;
   *status = PUSH -1;
}

可以正常工作。无论如何,您在 push() 调用期间分配内存,您在函数期间检查 top_stack == NULL 。或者,您可以在堆栈节点中有一个标志来指示它未使用(然后在推送期间您不会创建新的),但这对于您想要的内容来说太复杂了。

【讨论】:

    【解决方案2】:

    create_stack() 函数中,您分配内存并且不会将其初始化为任何东西。它的datalower 部分仍然是垃圾。

    当您弹出元素if (*top_stack == NULL) 时,条件永远不会变为真(成为垃圾值不为空),因此在删除所有节点后它返回垃圾值。

    【讨论】:

      猜你喜欢
      • 2019-05-18
      • 2015-11-16
      • 1970-01-01
      • 2013-01-20
      • 2016-08-17
      • 2014-10-16
      • 2015-08-05
      • 2012-12-20
      相关资源
      最近更新 更多