2012-10-21 14 views
2

我想編寫一個程序來計算後綴表達式,它包括一個驅動程序和一個實現文件。這兩個如下圖所示:爲什麼我的打印函數爲我的postfix程序產生這個錯誤?

#include <cstdlib> 
#include <iostream> 
#include <string> 
#include "Stack.h" 

using namespace std; 

void printStack(Stack<float>); 

int main() 
{ 
Stack<float> postFix; 
float userIn, operand1, operand2; 
// while the end of the postfix hasn't been reached 
do 
{ 
    // prompt user for next number or modulus command 
    cout << "ENTER: "; 
    if (!postFix.isEmpty()) printStack(postFix); 
    string userInput; 
    cin >> userInput; 

    // If user input is q or Q then terminate program 
    if (userInput == "q" || userInput == "Q") return 0; 
    else 
    { 
    // read next token by parsing userInput 
    // if token is a number push it onto stack 
    if (userInput != "+" && userInput != "/" && userInput != "*" && userInput != "-") 
    { 
    userIn = atof(userInput.c_str()); 
    postFix.push(userIn); 
    } 
    else if (!(postFix.size() < 2)) 
    { 
    // if it's not a number then pop element from the stack and call it 
    // operand2 
    operand2 = postFix.lastElem(); 
    postFix.pop(); 

    // pop another element from the stack; call it operand1 
    operand1 = postFix.lastElem(); 
    postFix.pop(); 

    // Perform the operation: operand1 token operand2 and 
    // push the result of the operation onto the stack 
    if (userInput == "/") 
     postFix.push((operand1/operand2)); 
    else if (userInput == "*") 
     postFix.push((operand1 * operand2)); 
    else if (userInput == "+") 
     postFix.push((operand1 + operand2)); 
    else if (userInput == "-") 
     postFix.push((operand1 - operand2)); 
    } 
    else if (postFix.size() < 2) 
    cout << "Stack is too small, request ignored\n"; 
} // end else 

} while (!postFix.isEmpty()); // end while 

// empty the stack 
postFix.makeEmpty(); 

return 0; 
} 

// The problem is in the print function! 

void printStack(Stack<float> postFix) 
{ 
    do 
    { 
    cout << postFix.lastElem() << " "; 
    postFix.pop(); 
    } while (!postFix.isEmpty()); 
} 

我實現文件如下所示:

#include <iostream> 
using namespace std; 

template <class DataType> 
class Stack 
{ 
    public: 
    Stack() // constructor 
    { 
    capacity = 2; 
    //Stack(capacity); 
    elements = new DataType[capacity]; 
    top = -1; 
    } 

    Stack(int s) // constructor with one parameter 
    { 
    capacity = s; 
    elements = new DataType[capacity]; 
    top = -1; 
    } 

~Stack() 
{ 
    delete [] elements; 
} 

bool isEmpty() const {return -1 == top;} 

void pop() // pop function 
{ 
    //if (-1 == top) return; // failed 
    top--; 
    if (top > 2 && top < (capacity/4)) 
    { 
    capacity /= 2; 
    changeSize(capacity); 
    } 
} 

DataType & lastElem() 
{ 
    return elements[top]; 
} 

int size() {return top;} 

void push(float parameter) // push function 
{ 
    if (++top == capacity) 
    { 
    capacity *= 2; 
    changeSize(capacity); 
    } 
    elements[top] = parameter; 
} 

bool peek(DataType& parameter) const 
{ 
    if (-1 == top) return false; // failed 
    parameter = elements[top]; 
    return true; // success 
} 

inline DataType & operator=(const Stack<DataType>& a) 
{ 
    if (this != &a) 
    { 
    delete [] elements; 
    elements = 0; 
    capacity = a.capacity; 
    if (capacity > 0) 
     elements = new DataType[capacity]; 
    for (int i = 0; i < capacity; i++) 
     elements[i] = a.elements[i]; 
    top = a.top; 
    } 
    return *this; 
} 

void changeSize(float newSize) // function for changing the array size if it's too small 
{ 
    DataType *newArray = new DataType[(int)newSize]; 
    int limit = (newSize > capacity)? capacity : newSize; 

    for (int i = 0; i < limit; i++) 
    { 
    newArray[i] = elements[i]; 
    } 
    delete [] elements; 
    elements = newArray; 
    capacity = newSize; 
} 

void makeEmpty() {top = -1;} 

private: 
    DataType* elements; 
    int capacity; 
    int top; // track newest value 
}; 

我編譯使用G ++這個程序後,我最多可以輸入兩個值,直到我得到如下一個奇怪的內存錯誤:

ENTER: 23 
ENTER: 23 43 
*** glibc detected *** ./calc: double free or corruption (fasttop): 0x0000000000c86010 *** 
======= Backtrace: ========= 
/lib/libc.so.6(+0x78b06)[0x7fbd11e4ab06] 
/lib/libc.so.6(cfree+0x73)[0x7fbd11e513d3] 
./calc[0x401197] 
./calc[0x400d9b] 
/lib/libc.so.6(__libc_start_main+0xfd)[0x7fbd11df0c4d] 
./calc[0x400c09] 
======= Memory map: ======== 
00400000-00402000 r-xp 00000000 08:06 788295        /home/badr/Documents/My programs/COMSC-210/calc 
00601000-00602000 r--p 00001000 08:06 788295        /home/badr/Documents/My programs/COMSC-210/calc 
00602000-00603000 rw-p 00002000 08:06 788295        /home/badr/Documents/My programs/COMSC-210/calc 
00c86000-00ca7000 rw-p 00000000 00:00 0         [heap] 
7fbd0c000000-7fbd0c021000 rw-p 00000000 00:00 0 
7fbd0c021000-7fbd10000000 ---p 00000000 00:00 0 
7fbd11dd2000-7fbd11f4f000 r-xp 00000000 08:06 5813      /lib/libc-2.11.1.so 
7fbd11f4f000-7fbd1214e000 ---p 0017d000 08:06 5813      /lib/libc-2.11.1.so 
7fbd1214e000-7fbd12152000 r--p 0017c000 08:06 5813      /lib/libc-2.11.1.so 
7fbd12152000-7fbd12153000 rw-p 00180000 08:06 5813      /lib/libc-2.11.1.so 
7fbd12153000-7fbd12158000 rw-p 00000000 00:00 0 
7fbd12158000-7fbd1216e000 r-xp 00000000 08:06 1268      /lib/libgcc_s.so.1 
7fbd1216e000-7fbd1236d000 ---p 00016000 08:06 1268      /lib/libgcc_s.so.1 
7fbd1236d000-7fbd1236e000 r--p 00015000 08:06 1268      /lib/libgcc_s.so.1 
7fbd1236e000-7fbd1236f000 rw-p 00016000 08:06 1268      /lib/libgcc_s.so.1 
7fbd1236f000-7fbd123f1000 r-xp 00000000 08:06 5814      /lib/libm-2.11.1.so 
7fbd123f1000-7fbd125f0000 ---p 00082000 08:06 5814      /lib/libm-2.11.1.so 
7fbd125f0000-7fbd125f1000 r--p 00081000 08:06 5814      /lib/libm-2.11.1.so 
7fbd125f1000-7fbd125f2000 rw-p 00082000 08:06 5814      /lib/libm-2.11.1.so 
7fbd125f2000-7fbd126e8000 r-xp 00000000 08:06 322753      /usr/lib/libstdc++.so.6.0.13 
7fbd126e8000-7fbd128e8000 ---p 000f6000 08:06 322753      /usr/lib/libstdc++.so.6.0.13 
7fbd128e8000-7fbd128ef000 r--p 000f6000 08:06 322753      /usr/lib/libstdc++.so.6.0.13 
7fbd128ef000-7fbd128f1000 rw-p 000fd000 08:06 322753      /usr/lib/libstdc++.so.6.0.13 
7fbd128f1000-7fbd12906000 rw-p 00000000 00:00 0 
7fbd12906000-7fbd12926000 r-xp 00000000 08:06 5815      /lib/ld-2.11.1.so 
7fbd12afa000-7fbd12afe000 rw-p 00000000 00:00 0 
7fbd12b21000-7fbd12b25000 rw-p 00000000 00:00 0 
7fbd12b25000-7fbd12b26000 r--p 0001f000 08:06 5815      /lib/ld-2.11.1.so 
7fbd12b26000-7fbd12b27000 rw-p 00020000 08:06 5815      /lib/ld-2.11.1.so 
7fbd12b27000-7fbd12b28000 rw-p 00000000 00:00 0 
7fff78cf3000-7fff78d08000 rw-p 00000000 00:00 0       [stack] 
7fff78dff000-7fff78e00000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
ENTER: 43 0 Aborted 

經過多次調試我已經確定的問題必須在位於.cpp文件的打印功能:

// The problem is in the print function! 

void printStack(Stack<float> postFix) 
{ 
    do 
    { 
    cout << postFix.lastElem() << " "; 
    postFix.pop(); 
    } while (!postFix.isEmpty()); 
} 

我只是不知道爲什麼發生或如何克服它。

回答

3

void printStack(Stack<float> postFix)以參數的值,所以做了一個副本。使用編譯器生成的拷貝構造函數。哪一個做了淺拷貝。你需要實現你自己的,做一個深層複製。

您已擁有一個複製賦值運算符(operator =)和一個析構函數。這是正確的,但還不夠。這兩個加上覆制構造函數Stack(const Stack<DataType>& other)組成了三條規則。如果你需要其中的一個,你需要全部。通常情況下,當你在班級中管理記憶時,你需要他們全部,你就是這樣。

實現類似於的operator =

DataType(const Stack<DataType>& a) 
{ 
    elements = 0; 
    capacity = a.capacity; 
    if (capacity > 0) 
     elements = new DataType[capacity]; 
    for (int i = 0; i < capacity; i++) 
     elements[i] = a.elements[i]; 
    top = a.top; 
} 

而且,萬一這不是教育目的,有一個預執行的頭<stack>,您可以使用std::stack

+0

擁有一個析構函數並不意味着需要一個複製賦值操作符或一個拷貝構造函數(儘管你需要一個自定義析構函數通常意味着你不能依賴默認的CAO或CC,這可能就是你的意思) 。 – Cubic

+0

非常感謝,我很感激!在我修復了複製構造函數之後,程序工作得很好。 – newwarrior21st

相關問題