堆叠推和弹出功能不起作用

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 本身。 您可以将其声明为指向堆栈指针的指针,并相应地更改主体(您需要双重解引用来分配 inflink)或通过在参数前添加 & 来使用引用参数姓名。同样的情况也适用于您的 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 的汉堡版中得到的是能够看到原始的 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;
}