在c程序中堆叠.pop操作不起作用



大家知道这个程序出了什么问题。我的pop操作有问题,即使堆栈为空,它也会显示一个额外的值??

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;
};

注:上述结构和功能必须使用d。。

#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 stackn");
scanf("%d",&m);
initstack(&p,m);
do {
printMenu();    
printf("Enter your choicen");
scanf("%d",&ch);
switch(ch) {
case 1:
printf("Enter the element to be pushedn");
scanf("%d",&data);
push(&p, data);
break;
case 2:
data1 = pop(&p);
if(data1 != -1000)
printf("The popped element is %dn",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 : Pushn");
printf("Choice 2 : Popn");
printf("Choice 3 : Displayn");
printf("Any other choice : Exitn");
}
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 fulln");
}
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 emptyn");
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;
}

让我们看看您的推送和弹出操作:

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

假设堆栈为空,top为-1。推送时,将top递增为0,并将元素写入p->a[0]。当弹出该元素时,首先将top递减到-1,然后尝试访问元素p->a[-1]

这是个问题。您不仅弹出了错误的元素,还访问了数组范围之外的元素并调用了未定义的行为。

访问所需元素后,您需要更改堆栈指针,如下所示:

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

对于基于阵列的堆栈,堆栈"向下"增长实际上更自然一些,比如:

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

这样,就不会冒访问数组范围之外的元素的风险。p->top将始终介于0和maxSize-1之间。

最后,一个风格说明:

您不需要强制转换malloc的结果;它只会增加视觉混乱,在某些情况下会抑制有用的诊断。你可以简单地写下:

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

CCD_ 8与CCD_;这样,如果您决定更改堆栈数组的类型,就不必担心更改malloc调用本身。省去了一些维护方面的麻烦,阅读更轻松。

编辑

以下是引起你头痛的部分原因:

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

如果堆栈已满,则打印一个警告,,然后无论如何都推送该元素

你需要一个else分支在那里

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

谢谢大家,我修好了…工作正常。谢谢你的建议。

#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 stackn");
scanf("%d",&m);
initstack(&p,m);
do {
printMenu();    
printf("Enter your choicen");
scanf("%d",&ch);
switch(ch) {
case 1:
printf("Enter the element to be pushedn");
scanf("%d",&data);
push(&p, data);
break;
case 2:
data1 = pop(&p);
if(data1 != -1000)
printf("The popped element is %dn",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 : Pushn");
printf("Choice 2 : Popn");
printf("Choice 3 : Displayn");
printf("Any other choice : Exitn");
}
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 fulln");
}
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 emptyn");
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;
}

您的显示逻辑有故障。它有一个off-by-one错误,并跳过最上面的元素。

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

在这部分,我认为你应该首先

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

然后

p->top --;
return result;

我也有同样的问题,这对我有帮助。

它认为这个问题与推送和弹出函数有关。两者都使用预注册,所以你推送的最后一个项目不是你弹出的第一个项目。

您的push执行以下操作:首先递增top,然后将值存储在a[top]中。所以top指向新推送的元素。

您的pop执行以下操作:首先递减top,然后检索a[top]处的值。检索到的值不会是最后一个推送的值,而是倒数第二个推送值。CCD_ 18一直指向这个非常相同的值。

我的建议:保持push不变,将pop改为:

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

因此,push将使顶部指向最后推送的值。pop将检索该值,然后递减top,使其指向要检索的下一个值。

最新更新