简体   繁体   English

在C程序中堆栈。 弹出操作不起作用

[英]STACK in c program. pop operation not working

Guys what is wrong with this program. 伙计们,这个程序有什么问题。 I am having problems with pop operation, it shows an extra value even after stack is empty. 我在执行弹出操作时遇到问题,即使堆栈为空,它也会显示一个额外的值。 ?? ??

void initstack (struct stack * p, int maxSize) 

void push (struct stack * p, int item) 

int pop (struct stack * p) 

void display (struct stack p) 

 struct stack

{

   int * a;

   int top;

   int maxSize;

};

Note:using d above structure and functions are mandatory.. 注意:使用以上结构和功能是强制性的。

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
struct stack {
    int * a;
    int top;
    int maxSize;
};
void initstack(struct stack * p, int maxSize);
void push(struct stack * p, int item);
int pop(struct stack * p);
void display(struct stack p);
int StackIsEmpty(struct stack * p);
int StackIsFull(struct stack * p);
void printMenu();

int main()  {
    struct stack p;
    int data,ch, data1, m;
    printf("Enter the maximum size of the stack\n");
    scanf("%d",&m);
    initstack(&p,m);
    do {
    printMenu();    
    printf("Enter your choice\n");
    scanf("%d",&ch);
    switch(ch) {
      case 1:
        printf("Enter the element to be pushed\n");
        scanf("%d",&data);
        push(&p, data);
        break;
      case 2:
        data1 = pop(&p);
        if(data1 != -1000)
        printf("The popped element is %d\n",data1);
        break;
      case 3:
        printf("The contents of the stack are");
        display(p);
        printf("\n");
        break;
      default:
        exit(0);
    }
    } while(1);
    return 0;
}

void printMenu()
{
    printf("Choice 1 : Push\n");
    printf("Choice 2 : Pop\n");
    printf("Choice 3 : Display\n");
    printf("Any other choice : Exit\n");
}

void initstack(struct stack * p, int maxSize) {
    int *newContents;
  newContents=(int *)malloc(sizeof(int)*maxSize);
  p->a=newContents;
  p->maxSize=maxSize;
  p->top=-1; 
}

void push(struct stack * p, int item) {
    if(StackIsFull(p))
    {
      printf("Stack is full\n");
    }
  p->a[++p->top]=item;
}

void display(struct stack p) {
  int i;
  struct stack *b=&p;
  if(StackIsEmpty(b))
    printf(" {}");
  for(i=0;i<b->top;i++)
  {
    printf(" %d",b->a[i]);
  }
}

int pop(struct stack * p) {
    if(StackIsEmpty(p))
    {
      printf("Stack is empty\n");
      return -1000;
    }
  else
    return p->a[--p->top];
}

int StackIsEmpty(struct stack *p)
{
  return p->top == -1;          //p->top==-1;
}

int StackIsFull(struct stack *p)
{
  return p->top >= p->maxSize-1;
}

Let's look at your push and pop operations: 让我们看看您的推入和弹出操作:

p->a[++p->top]=item; // push
p->a[--p->top];      // pop

Let's assume the stack is empty and top is -1. 假设堆栈为空,并且top为-1。 When you do a push, you increment top to 0 and write your element to p->a[0] . 进行推送时,将top递增至0,然后将元素写入p->a[0] When you pop that element, you first decrement top back to -1, and then try to access the element p->a[-1] . 弹出该元素时,首先将top递减为-1,然后尝试访问元素p->a[-1]

This is a problem. 这是个问题。 Not only are you popping the wrong element, you're accessing an element outside the range of your array and invoking undefined behavior. 不仅弹出错误的元素,而且正在访问数组范围之外的元素并调用未定义的行为。

You need to change the stack pointer after you access the element you want, like so: 访问所需的元素后,需要更改堆栈指针,如下所示:

p->a[++p->top] = item; // push
item = p->a[p->top--]; // pop

For array-based stacks, it's actually a little more natural for the stack to grow "downwards", like so: 对于基于数组的堆栈,实际上,堆栈“向下”增长更自然一些,如下所示:

p->top = p->maxSize = maxSize; // init

if ( p->top )            // p->top != 0 means room left on the stack
  p->a[--p->top] = item; // push

if ( p->top < p->maxSize ) // p->top < p->maxSize means elements left on stack 
  return p->a[p->top++];   // pop

This way, you don't run the risk of accessing an element outside the range of the array. 这样,您就不会冒访问数组范围之外的元素的风险。 p->top will always be between 0 and maxSize - 1. p->top始终在0到maxSize-1之间。

Finally, a style note: 最后,一个样式说明:

You don't need to cast the result of malloc ; 您无需malloc的结果; it just adds visual clutter, and in some cases can suppress a useful diagnostic. 它只会增加视觉混乱,并且在某些情况下可以抑制有用的诊断。 You can clean it up by simply writing: 您可以通过简单地编写来清理它:

 /**
  * Whitespace is your friend.  Use it.
  */
 newContents = malloc( sizeof *newContents * maxSize );

sizeof *newContents is the same as sizeof (int) ; sizeof *newContentssizeof (int)相同; this way, if you ever decide to change the type of the stack array, you don't have to worry about changing the malloc call itself. 这样,如果您决定更改堆栈数组的类型,则不必担心更改malloc调用本身。 Saves some maintenance headaches, reads a little easier. 节省了一些维护工作的麻烦,阅读起来也容易一些。

Edit 编辑

Here's part of what's causing your headaches: 这是引起您头痛的部分原因:

void push(struct stack * p, int item) {
    if(StackIsFull(p))
    {
      printf("Stack is full\n");
    }
    p->a[++p->top]=item; // DANGER WILL ROBINSON!
}

If the stack is full you print a warning, and then you push the element anyway . 如果堆栈已满,则打印警告, 然后无论如何都要推动该元素

You need an else branch in there 你需要在那里的else分支

void push(struct stack * p, int item) 
{
  if(StackIsFull(p))
  {
    printf("Stack is full\n");
  }
  else { p->a[++p->top]=item; }
}

Thanks guys, I fixed it.. works fine. 谢谢大家,我修复了..效果很好。 thanks for all ur suggestions. 感谢您的所有建议。

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
struct stack {
    int * a;
    int top;
    int maxSize;
};
void initstack(struct stack * p, int maxSize);
void push(struct stack * p, int item);
int pop(struct stack * p);
void display(struct stack p);
int StackIsEmpty(struct stack * p);
int StackIsFull(struct stack * p);
void printMenu();

int main()  {
    struct stack p;
    int data,ch, data1, m;
    printf("Enter the maximum size of the stack\n");
    scanf("%d",&m);
    initstack(&p,m);
    do {
    printMenu();    
    printf("Enter your choice\n");
    scanf("%d",&ch);
    switch(ch) {
      case 1:
        printf("Enter the element to be pushed\n");
        scanf("%d",&data);
        push(&p, data);
        break;
      case 2:
        data1 = pop(&p);
        if(data1 != -1000)
        printf("The popped element is %d\n",data1);
        break;
      case 3:
        printf("The contents of the stack are");
        display(p);
        printf("\n");
        break;
      default:
        exit(0);
    }
    } while(1);
    return 0;
}

void printMenu()
{
    printf("Choice 1 : Push\n");
    printf("Choice 2 : Pop\n");
    printf("Choice 3 : Display\n");
    printf("Any other choice : Exit\n");
}

void initstack(struct stack * p, int maxSize) {
    int *newContents;
  newContents=malloc(sizeof(int)*maxSize);
  p->a=newContents;
  p->maxSize=maxSize;
  p->top=-1; 
}

void push(struct stack * p, int item) {
    if(StackIsFull(p))
    {
      printf("Stack is full\n");
    }
    else
    {
    p->a[++p->top]=item;  //FIXED LINE, ELSE BLOCK ADDED
    }
}

void display(struct stack p) {
  int i;
  struct stack *b=&p;
  if(StackIsEmpty(b))
    printf(" {}");
  for(i=0;i<=b->top;i++)   //FIXED PREVIOUSLY for(i=0;i<b->top;i++)
  {
    printf(" %d",b->a[i]);
  }
}

int pop(struct stack * p) {
    if(StackIsEmpty(p))
    {
      printf("Stack is empty\n");
      return -1000;
    }
  else
    return p->a[p->top--];     //FIXED PREVIOUSLY p->a[--p->top];
}

int StackIsEmpty(struct stack *p)
{
  return p->top < 0;          //FIXED PREVIOUSLY p->top==-1;
}

int StackIsFull(struct stack *p)
{
  return p->top >= p->maxSize-1;
}

Your display logic is faulty. 您的显示逻辑有问题。 It has an off-by-one error and skips the topmost element. 它有一个偏离一的错误,并跳过最上面的元素。

return p->a[--p->top];

In this part I think you should first 在这一部分,我认为您应该首先

int result =  p->a[p->top];

then 然后

p->top --;
return result;

I had same issue and that helped me. 我遇到了同样的问题,这对我有所帮助。

It hink the problem is related to push and pop functions. 它认为问题与推送和弹出功能有关。 Both use preincrements, so the last item you push is not the first item you pop. 两者都使用预增量,因此您推送的最后一项不是您弹出的第一项。

Your push does: first increment top , then store value in a[top] . 您的push会:首先递增top ,然后将值存储在a[top] So top is pointing to the newly pushed element. 所以top指向新推的元素。

Your pop does: first decrement top , then retrieve the value at a[top] . 您的pop执行以下操作:首先递减top ,然后在a[top]处检索值。 The value retrieved won't be the last pushed, but the previous-to-last. 检索到的值不是最后推送的,而是倒数第二个。 top keeps pointing at this very same value. top始终指向相同的值。

My suggestion: leave push as is, and change pop as this: 我的建议:保持push不变,并按以下方式更改pop

int pop(struct stack * p) {
    if(StackIsEmpty(p))
    {
      printf("Stack is empty\n");
      return -1000;
    }
  else
    return p->a[p->top--]; /* post-increment!! */
}

So, push will leave top pointing at the last pushed value. 因此, push将使顶部指向最后推送的值。 pop will retrieve this value, then decrement top , leaving it pointing at the next value to retrieve. pop将检索此值,然后递减top ,使其指向要检索的下一个值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM