使用推送和弹出功能无法正常工作

时间:2015-06-14 16:33:26

标签: c++ null crash stack

这是该计划。

#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()只是不起作用。如果我在if(start)之前添加pop它只是跳过它,让我认为在push完成后堆栈会以某种方式变为NULL。基本上一切都有效,直到它到达cout << "popped " << start->inf;行,当它刚崩溃(没有错误消息)时再次让我认为堆栈在到达pop()之前变为空。有什么建议吗?

3 个答案:

答案 0 :(得分:1)

首先,你的两个函数的签名都很奇怪:

start

假设p指向堆栈顶部,您应该丢弃push。它应该是函数的局部变量,而不是参数。

其次,让我们看看p = start; start = new stack; start->inf = s; start->link = p; 实施:

start

这个看起来很好。您错过的是start被声明为堆栈指针,您正在更改函数内部的指针,这是一个值参数而不是引用。使用您当前的签名,您可以更改start POINTS TO,而不是inf本身。 您可以将其声明为指向堆栈的指针,并相应地更改主体(您需要双重取消引用以分配link&)或通过在参数前添加pop来使用引用参数名称。同样的情况适用于您的{{1}}功能。

答案 1 :(得分:0)

这里你如何引用指针:

void push(stack*&, stack*&, int);
void pop(stack*&, stack*&);

答案 2 :(得分:0)

之前的答案是正确的,但它们并没有真正解释原因。

这里使用的开始和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中获得的内容是能够查看原始startp。因为同时允许两个具有相同名称的变量会导致完全混淆(严重的是,哪一个被使用?)最内层的定义隐藏了所有外部定义。因此push的{​​{1}}不仅不是全局定义的start,而start的{​​{1}}也阻止了对全局push的访问。

但是,如果您定义并且不更改内容

start

startvoid 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使用全局cheeseburgerpush

现在考虑如果某人修改了您的代码并错误地遗漏了start会发生什么。

p

p仍然是一个有效的变量,代码仍然很乐意编译,并使用了错误的void push(stack *start, int s)

在重用变量名之前请仔细考虑。我喜欢标记全局变量,以便我可以看到它们何时被使用,因此它们不太可能与本地人发生冲突。对我来说,开始是gStart。它看起来很奇怪,可以脱颖而出,不太可能被意外使用。

OP的代码还不错。需要测试有效的整数输入和弹出空堆栈

p