2015-06-14 79 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; 
}