2015-06-14 78 views
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; 


} 

这是一个简单的程序,让我push和pop的项目,并从堆栈,但出于某种原因,pop()是行不通的。如果我在pop之前添加if(start),它只是跳过它,使我认为在push完成之后堆栈以某种方式变为NULL。基本上所有东西都可以工作,直到它到达cout << "popped " << start->inf;行,当它刚刚崩溃时(没有错误信息),这又使我认为堆栈在到达pop()之前变为空。有什么建议么?

+0

推的逻辑貌似可以在max.You跟踪只有两个推的需要重新思考逻辑。 –

+0

您正在按价值传递您的指针。所以在运行push start之后,p在main()中保持不变。 – drescherjm

+0

在这段代码中,'start'是一个由'NULL'(隐含地)初始化的指针。你为什么期望它是非空的? –

回答

1

首先,无论你的函数的签名是怪异:

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功能。

+0

我有点难以理解,但在@Valeri Atamaniouk的帮助下,我明白了。 Chaning“stack * start”到“stack *&start”(和其他所有相应的)修复了这个问题,谢谢。我很困惑,因为朋友告诉我,当你使用一个指针参数时,它就像数组一样被自动用作引用(你不必为数组参数放置&infront以便改变被记住在函数之外) ,但我想它不适合指针? – user3455974

+0

@ user3455974将指针看作包含地址的变量。 'stack * p'传入一个地址。该函数获得该地址的副本。如果你想改变函数内部的地址,你必须更进一步,并提供该地址的地址。考虑到指针'stack *&p'的引用,此处优先于指向“stack ** p”指针的指针,因为&提供了有关如何提供和使用该地址的保护性限制。 – user4581301

0

在这里,您如何让指针的参考:

void push(stack*&, stack*&, int); 
void pop(stack*&, stack*&); 
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。因为同时允许具有相同名称的两个变量会导致完全混淆(严重的是,哪一个被使用?),最内部的定义隐藏了所有的外部定义。因此,不仅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; 
}