[英]Stack with push and pop functions not working
这是程序。
#include<iostream>
#include<string>
using namespace std;
struct stack
{
int inf;
stack* link;
} *start, *p;
void push(stack*, stack*, int);
void pop(stack*, stack*);
int main()
{
int s = 0;
string thing;
cin >> thing;
while (thing != "end")
{
if (thing == "push")
{
push(start, p, s);
}
if (thing == "pop")
{
pop(start, p);
}
cin >> thing;
}
return 0;
}
void push(stack *start, stack *p, int s)
{
cin >> s;
p = start;
start = new stack;
start->inf = s;
start->link = p;
cout << "pushed " << start->inf << endl;
}
void pop(stack *start, stack *p)
{
cout << "popped " << start->inf;
p = start;
start = start->link;
delete p;
}
这是一个简单的程序,允许我将项目推入堆栈或从堆栈中pop()
,但是由于某些原因, pop()
不能正常工作。 如果我在pop
之前添加if(start)
,它将跳过它,使我认为堆栈在push
完成后以某种方式变为NULL。 基本上,一切都会起作用,直到到达cout << "popped " << start->inf;
一行,当它只是崩溃(没有错误消息)时,这再次让我认为堆栈在到达pop()
之前变为null。 有什么建议么?
首先,两个函数的签名都很奇怪:
void push(stack *start, stack *p, int s)
void pop(stack *start, stack *p)
假设start
位于堆栈顶部,则应丢弃p
。 它应该是函数的局部变量,而不是参数。
其次,让我们看看push
实现:
p = start;
start = new stack;
start->inf = s;
start->link = p;
这个看起来不错。 您错过的是将start
声明为堆栈指针,并且您正在函数内部更改指针,该指针是一个值参数而不是引用。 使用当前的签名,您可以更改以POINTS TO start
,但不能自行start
。 您可以将其声明为指向堆栈的指针,然后相应地更改主体(分配inf
和link
需要双重取消引用),或在参数名称前添加&
使用引用参数。 同样的情况也适用于您的pop
功能。
这里是如何引用指针的:
void push(stack*&, stack*&, int);
void pop(stack*&, stack*&);
先前的答案是正确的,但它们并没有真正解释原因。
此处使用的开始和p
void push(stack *start, stack *p, int s)
与此处定义的不同。
struct stack
{
int inf;
stack* link;
} *start, *p;
push
具有一个全新的开始和p,它可能是另一个开始和p的副本,但它们并不相同。 可以定义推送
void push(stack *hamburger, stack *cheeseburger, int s)
对函数内部使用的变量进行相应的更改,您将不会发现函数的行为有所不同。
在汉堡版本的push
中,您将看到原始的start
和p
。 因为同时允许两个具有相同名称的变量会导致完全混乱(严重的是,哪个变量被使用了?),所以最里面的定义隐藏了所有外部的定义。 因此,不仅push
的start
不是全局定义的start
,而且push
的start
也阻止了对全局start
访问。
但是,如果您定义并且不更改内容
void push(stack *hamburger, stack *cheeseburger, int s)
{
cin >> s;
p = start;
start = new stack;
start->inf = s;
start->link = p;
cout << "pushed " << start->inf << endl;
}
hamburger
和cheeseburger
什么都没用, push
使用全球start
和p
现在考虑如果有人修改您的代码并错误地遗漏了p
会发生什么。
void push(stack *start, int s)
p
仍然是有效变量,代码仍然可以愉快地编译,并且使用错误的p
。
重用变量名之前请仔细考虑。 我喜欢标记全局变量,以便可以看到何时使用它们,因此它们与本地变量发生冲突的可能性较小。 对我来说,开始将是gStart。 它看起来很奇怪,足以脱颖而出,不太可能被偶然使用。
OP的代码还不错。 需要测试有效的整数输入和弹出空堆栈
#include<iostream>
#include<string>
using namespace std;
struct stack
{
int inf;
stack* link;
} *gStart; // don't need p at all start renamed to avoid collisions
void push(stack * & start)
{
stack *p; //just holds a temporary no need to pass
int s; // same as above
while (!(cin >> s)) // read and test the input
{ // bad input. Clear stream and prompt
cin.clear();
cout << "nice try, wiseguy. Gimmie an int!" << endl;
}
p = new stack();
p->inf = s;
p->link = start;
start = p;
cout << "pushed " << start->inf << endl;
}
void pop(stack *& start)
{
stack *p; //no need to pass in
if (start != NULL)
{ // don't pop list if list empty
cout << "popped " << start->inf << endl;
p = start;
start = p->link;
delete p;
}
else
{
cout << "stack empty" << endl;
}
}
int main()
{
// there is no need for start to be global. It could just as easily be allocated here.
string thing;
cin >> thing;
while (thing != "end")
{
if (thing == "push")
{
push(gStart);
}
else if (thing == "pop")
{
pop(gStart);
}
cin >> thing;
}
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.