这个程序有什么问题。我遇到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 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;
}
答案 0 :(得分: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
对于基于数组的堆栈,它实际上更有利于堆栈增长&#34;向下&#34;,如下所示:
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;
}
}
答案 1 :(得分:1)
谢谢大家,我修好了......工作正常。谢谢你的所有建议。
#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;
}
答案 2 :(得分:0)
您的显示逻辑有问题。它有一个off-by-one错误并跳过最顶层的元素。
答案 3 :(得分:0)
int result = p->a[p->top];
在这部分我认为你应该先
p->top --;
return result;
然后
@Override
public boolean onInterceptTouchEvent (MotionEvent ev) {
getMaxLeftScroll();
myLastX = ev.getX();
myLastY = ev.getY();
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(final MotionEvent ev){
final int action = ev.getAction();
final float x;
final float y;
switch (action) {
case MotionEvent.ACTION_MOVE:
// This handles Scrolling only.
x = ev.getX();
y = ev.getY();
final int deltaX = (int) (myLastX - x);
final int deltaY = (int) (myLastY - y);
if(Math.abs(deltaX) > Math.abs(deltaY)) {
if( (iCurrentLeftScroll+deltaX) > 0 &&
iCurrentLeftScroll+deltaX < iMaxLeftScroll) {
scrollBy(deltaX, 0);
//Listener and call the method here to scroll the header
mScrollChangeListener.onGridViewScrolled(deltaX);
iCurrentLeftScroll+=deltaX;
} //Scrolled by some value
// Close to right edge within 10? Smooth Scroll remaining small distance if not already there
else if(deltaX > 0 && (iCurrentLeftScroll<iMaxLeftScroll)) {
if ((iMaxLeftScroll - iCurrentLeftScroll) < 10) {
scrollBy(iMaxLeftScroll-iCurrentLeftScroll, 0);
mScrollChangeListener.onGridViewScrolled(iMaxLeftScroll-iCurrentLeftScroll);
iCurrentLeftScroll = iMaxLeftScroll;
}
}
// Close to left edge within 30? Smooth Scroll remaining small distance if not already there
else if(deltaX < 0 && (iCurrentLeftScroll>0)) {
if ((iCurrentLeftScroll) < 10) {
scrollBy(iCurrentLeftScroll*-1, 0);
mScrollChangeListener.onGridViewScrolled(iCurrentLeftScroll*-1);
iCurrentLeftScroll = 0;
}
}
//left and right are subjective
if(iCurrentLeftScroll == iMaxLeftScroll)
iScrollStatus = SCROLLED_FULL_LEFT;
if(iCurrentLeftScroll == 0)
iScrollStatus = SCROLLED_FULL_RIGHT;
if( (iCurrentLeftScroll > 0) && (iCurrentLeftScroll < iMaxLeftScroll) )
iScrollStatus = 0;
Log.d(TAG," Scroll Status " + String.valueOf(iScrollStatus) );
Log.d(TAG," MaxLeftScroll " + String.valueOf(iMaxLeftScroll) );
Log.d(TAG," Current Left Scroll " + String.valueOf(iCurrentLeftScroll) );
}
myLastX = x;
myLastY = y;
break;
}
return super.onTouchEvent(ev);
}
我有同样的问题,这帮助了我。
答案 4 :(得分:0)
这个问题与推送和弹出功能有关。两者都使用preincrements,因此您推送的最后一个项目不是您弹出的第一个项目。
您的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
,使其指向要检索的下一个值。