大家知道这个程序出了什么问题。我的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
,使其指向要检索的下一个值。