堆叠推和弹出功能不起作用
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
之前添加一个 if(start)
它只是跳过它,让我认为堆栈在 push
完成后以某种方式变为 NULL。基本上一切正常,直到到达 cout << "popped " << start->inf;
行,当它崩溃时(没有错误消息),这再次让我认为堆栈在到达 pop()
之前变为空。有什么建议吗?
首先,你的两个函数的签名都很奇怪:
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
被声明为指向堆栈的指针,并且您正在更改函数内部的指针,这是一个值参数而不是引用。使用您当前的签名,您可以更改 start
指向的内容,但不能更改 start
本身。
您可以将其声明为指向堆栈指针的指针,并相应地更改主体(您需要双重解引用来分配 inf
和 link
)或通过在参数前添加 &
来使用引用参数姓名。同样的情况也适用于您的 pop
函数。
引用指针的方法如下:
void push(stack*&, stack*&, int);
void pop(stack*&, stack*&);
前面的答案是正确的,但并没有真正解释原因。
这里使用的start和p
void push(stack *start, stack *p, int s)
与此处定义的不同。
struct stack
{
int inf;
stack* link;
} *start, *p;
push
有一个全新的 start 和 p,它可能是另一个 start 和 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;
}
这是程序。
#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
之前添加一个 if(start)
它只是跳过它,让我认为堆栈在 push
完成后以某种方式变为 NULL。基本上一切正常,直到到达 cout << "popped " << start->inf;
行,当它崩溃时(没有错误消息),这再次让我认为堆栈在到达 pop()
之前变为空。有什么建议吗?
首先,你的两个函数的签名都很奇怪:
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
被声明为指向堆栈的指针,并且您正在更改函数内部的指针,这是一个值参数而不是引用。使用您当前的签名,您可以更改 start
指向的内容,但不能更改 start
本身。
您可以将其声明为指向堆栈指针的指针,并相应地更改主体(您需要双重解引用来分配 inf
和 link
)或通过在参数前添加 &
来使用引用参数姓名。同样的情况也适用于您的 pop
函数。
引用指针的方法如下:
void push(stack*&, stack*&, int);
void pop(stack*&, stack*&);
前面的答案是正确的,但并没有真正解释原因。
这里使用的start和p
void push(stack *start, stack *p, int s)
与此处定义的不同。
struct stack
{
int inf;
stack* link;
} *start, *p;
push
有一个全新的 start 和 p,它可能是另一个 start 和 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;
}