![](/img/trans.png)
[英]malloc function is not working properly in C program. the program crashes
[英]STACK in c program. pop operation not working
伙计们,这个程序有什么问题。 我在执行弹出操作时遇到问题,即使堆栈为空,它也会显示一个额外的值。 ??
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;
};
注意:使用以上结构和功能是强制性的。
#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;
}
让我们看看您的推入和弹出操作:
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 );
sizeof *newContents
与sizeof (int)
相同; 这样,如果您决定更改堆栈数组的类型,则不必担心更改malloc
调用本身。 节省了一些维护工作的麻烦,阅读起来也容易一些。
编辑
这是引起您头痛的部分原因:
void push(struct stack * p, int item) {
if(StackIsFull(p))
{
printf("Stack is full\n");
}
p->a[++p->top]=item; // DANGER WILL ROBINSON!
}
如果堆栈已满,则打印警告, 然后无论如何都要推动该元素 。
你需要在那里的else
分支
void push(struct stack * p, int item)
{
if(StackIsFull(p))
{
printf("Stack is full\n");
}
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 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;
}
您的显示逻辑有问题。 它有一个偏离一的错误,并跳过最上面的元素。
return p->a[--p->top];
在这一部分,我认为您应该首先
int result = p->a[p->top];
然后
p->top --;
return result;
我遇到了同样的问题,这对我有所帮助。
它认为问题与推送和弹出功能有关。 两者都使用预增量,因此您推送的最后一项不是您弹出的第一项。
您的push
会:首先递增top
,然后将值存储在a[top]
。 所以top指向新推的元素。
您的pop
执行以下操作:首先递减top
,然后在a[top]
处检索值。 检索到的值不是最后推送的,而是倒数第二个。 top
始终指向相同的值。
我的建议:保持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!! */
}
因此, push
将使顶部指向最后推送的值。 pop
将检索此值,然后递减top
,使其指向要检索的下一个值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.