繁体   English   中英

带有推入和弹出功能的堆栈不起作用

[英]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 您可以将其声明为指向堆栈的指针,然后相应地更改主体(分配inflink需要双重取消引用),或在参数名称前添加&使用引用参数。 同样的情况也适用于您的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中,您将看到原始的startp 因为同时允许两个具有相同名称的变量会导致完全混乱(严重的是,哪个变量被使用了?),所以最里面的定义隐藏了所有外部的定义。 因此,不仅pushstart不是全局定义的start ,而且pushstart也阻止了对全局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;
}

hamburgercheeseburger什么都没用, push使用全球startp

现在考虑如果有人修改您的代码并错误地遗漏了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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM