2013-10-08 2 views
0

Мне нужно создать калькулятор RPN (postfix notation), который выполняет простые операции (+, -, *, /), используя связанный список для поддержки стека. Я получил большинство из них, но я столкнулся с несколькими проблемами. Я могу вычислить любые два числа с одним операндом (например: 5 5 + = 10), но не может сделать ничего больше. Я провел некоторое исследование в Интернете и наблюдал за несколькими видеороликами YouTube, чтобы добраться туда, где я сейчас, но большинство используют ссылку на стек, чтобы сделать это. Я попытался объединить учебники по этому поводу, а также как создать собственный стек.Проблемы вычисления постфиксного выражения с более чем двумя операндами

Я довольно новичок в этом и довольно потерял способ вычисления большего выражения (например: 5 5 5 + + = 15), и мне также нужно проверить наличие ошибок, которые я выполнил, но с которыми я борюсь, - «слишком много операторов» и «слишком много операндов». С слишком большим количеством операторов я предполагаю, что это имеет какое-то отношение к тому, что вы не можете выкинуть значение, потому что там нет никого, но это насколько я могу (если он прав, все еще не совсем уверен, как реализовать Это). Любая помощь в любой из этих трех вещей или что-то еще, что вы можете увидеть здесь, будет очень оценена.

#include<iostream> 
#include<string> 
#include<sstream> 
#include<iomanip> 

using namespace std; 

class SLLNode 
{ 
    double data; 
    SLLNode *top; 
    SLLNode *ptr; 
public: 
    SLLNode() 
    { 
     top = NULL; 
     ptr = NULL; 
    } 
    void pushVal(double val) 
    { 
     SLLNode *next = new SLLNode; 
     next -> data = val; 
     next -> ptr = top; 
     top = next; 
    } 
    double popVal() 
    { 
     SLLNode *next = new SLLNode; 
     next = top; 
     top = top -> ptr; 
     next -> ptr = NULL; 
     return next -> data; 
     delete next; 
    } 
    void print() 
    { 
     SLLNode *next = new SLLNode; 
     next = top; 
     cout << "= " << next -> data << endl << ">>"; 
     next = next -> ptr; 
     delete next; 
    } 
}; 

bool isOperator(const string& input) 
{ 
    string ops[] = {"+", "-", "*", "/"}; 
    for(int i = 0; i < 4; i++) 
    { 
     if(input == ops[i]) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

void performOp(const string& input, SLLNode& stack) 
{ 
    double fVal, sVal; 
    int result = 0; 

    sVal = stack.popVal(); 
    fVal = stack.popVal(); 

    if(input == "+") 
    { 
     stack.pushVal(fVal + sVal); 
    } 
    else if(input == "-") 
    { 
     stack.pushVal(fVal - sVal); 
    } 
    else if(input == "*") 
    { 
     stack.pushVal(fVal*+ sVal); 
    } 
    else if(input == "/" && sVal != 0) 
    { 
     stack.pushVal(fVal/sVal); 
    } 

    if(input == "/" && sVal == 0) 
    { 
     cout << "Error: Division by zero" << endl; 
     result = 1; 
    } 

    if(result == 0) 
    { 
     stack.print(); 
    } 
} 

int main() 
{ 
    string input; 
    SLLNode stack; 

    cout << "::::::::::::::::RPN CALCULATOR:::::::::::::::::" << endl; 
    cout << "::TYPE IN A POSTFIX EXPRESSION OR 'q' TO QUIT::" << endl; 
    cout << ":::::::::::::::::::::::::::::::::::::::::::::::" << endl << endl; 

    cout << ">>"; 
    while(true) 
    { 
     cin >> input; 
     double num; 

     if(istringstream(input) >> num) 
     { 
      stack.pushVal(num); 
     } 
     else if (isOperator(input)) 
     { 
      performOp(input, stack); 
     } 
     else if (input == "q") 
     { 
      return 0; 
     } 
     else 
     { 
      cout << "Error: Invalid input" << endl; 
     } 
    } 
} 

ответ

1

Прежде всего, я рекомендую вам использовать std::map<double> вместо того, чтобы переводить свой собственный связанный список, если только он не предназначен для обучения.

Основная проблема заключается в SLLNode::popVal() и SLLNode::print(), где все немного запуталось.

Вот что вам нужно изменить, чтобы исправить это:

double popVal() 
{ 
    SLLNode *next = top -> ptr; 
    double ret = top -> data; 
    delete top; 
    top = next; 
    return ret; 
} 
void print() 
{ 
    cout << "= " << top -> data << endl << ">>"; 
} 

Есть много других вещей, которые вы могли бы улучшить в своем коде, но это должно ответить на ваш вопрос.

+0

Фантастично, большое вам спасибо.Сейчас все работает по большей части, просто нужно много сделать, но нужно сначала выполнить основную функцию. Я действительно, действительно, ценю это. – Tyler

0

У вас есть два оператора: '*' и '+' в вашем выражении для вычисления умножения. Я добавил & переставить немного проверки ошибок,

int 
performOp(const string& input, SLLNode& stack) 
{ 
    double fVal, sVal; 
    int result = 0; 

    if(stack.size < 2) 
    { 
     cout << "Error: too few operands" << end; 
     stack.print(); 
     return 1; 
    } 

    sVal = stack.popVal(); 
    fVal = stack.popVal(); 

    if(input == "+") 
    { 
     stack.pushVal(fVal + sVal); 
    } 
    else if(input == "-") 
    { 
     stack.pushVal(fVal - sVal); 
    } 
    else if(input == "*") 
    { 
     stack.pushVal(fVal * sVal); //problem was here 
    } 
    else if(input == "/") 
    { 
     if(sVal == 0) 
     { 
      cout << "Error: Division by zero" << endl; 
      stack.print(); 
      return 1; 
     } 
     stack.pushVal(fVal/sVal); 
    } 

    return 0; 
} 

Определить узел списка, который содержит головку/хвост, и подсчитывает элементы в стеке,

#include<iostream> 
#include<string> 
#include<sstream> 
#include<iomanip> 
using namespace std; 

class SLLNode //single link list 
{ 
public: 
    SLLNode *next; 
    double data; 
    SLLNode() 
    { 
     next = NULL; 
     data = 0; 
    } 
    void print() 
    { 
     SLLNode *node = NULL; 
     cout << "= " << data << endl << ">>"; 
    } 
}; 

Ваша реализация стека утечки памяти, выделяет ненужных узлов и не хватает нескольких полезных операций стека, которые помогут вам решить некоторые из ваших проблем. Вам нужен деструктор, который опустошает ваш список, если вы его забудете, и это поможет распечатать весь список. Во всяком случае,

class SLList //single link list 
{ 
    SLLNode *head; 
    SLLNode *tail; 
    int _count; 
public: 
    SLList() 
    { 
     head = NULL; 
     tail = NULL; 
     _count = 0; 
    } 
    ~SLList() 
    { 
     while(!empty()) { pop(); } 
    } 
    int size() { return _count; } 
    bool empty() { return (!head); return false; } 
    void push(double val) 
    { 
     SLLNode *node = new SLLNode; 
     node->data = val; 
     node->next = head; 
     ++_count; 
     if(!tail) tail = node; 
     head = node; 
    } 
    double pop() 
    { 
     SLLNode *node = NULL; 
     if(!head) return 0; 
     node = head; 
     double val = node->data; 
     head = node->next; 
     --_count; 
     if(!head) tail = NULL; 
     delete node; 
     return val; 
    } 
    double tip() 
    { 
     SLLNode *node = NULL; 
     if(!head) return 0; 
     node = head; 
     double val = node->data; 
     return val; 
    } 
    void print() 
    { 
     SLLNode *node = NULL; 
     if(!head) return; 
     for(node=head; node; node=node->next) 
      node->print(); 
    } 
}; 

Вы можете добавить больше операторов, извлечь что

bool isOperator(const string& input); 
int performOp(const string& input, SLList& stack); 
static string BINOPS[] = {"+", "-", "*", "/"}; 

bool 
isOperator(const string& input) 
{ 
    for(int i = 0; i < 4; i++) //should get size of BINOPS 
    { 
     if(input == BINOPS[i]) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

Проверьте STACKSIZE до извлечения элементов из вашего стека,

int 
performOp(const string& input, SLList& stack) 
{ 
    double fVal, sVal; 
    int result = 0; 

    if(stack.size() < 2) 
    { 
     cout<<"Error: too few operands"<<endl; 
     stack.print(); 
     return 1; 
    } 

    sVal = stack.pop(); 
    fVal = stack.pop(); 

    if(input == "+") 
    { 
     stack.push(fVal + sVal); 
    } 
    else if(input == "-") 
    { 
     stack.push(fVal - sVal); 
    } 
    else if(input == "*") 
    { 
     stack.push(fVal * sVal); 
    } 
    else if(input == "/") 
    { 
     if(sVal == 0) 
     { 
      cout << "Error: Division by zero" << endl; 
      stack.print(); 
      return 1; 
     } 
     stack.push(fVal/sVal); 
    } 

    return 0; 
} 

Вы должны каким-то образом распечатайте свой список. Язык вперед используется «„ так что здесь я добавил случай, чтобы напечатать список с помощью“.»,

int 
main() 
{ 
    string input; 
    SLList stack; 

    cout<<"::::::::::::::::RPN CALCULATOR:::::::::::::::::"<<endl; 
    cout<<"::TYPE IN A POSTFIX EXPRESSION OR 'q' TO QUIT::"<<endl; 
    cout<<":::::::::::::::::::::::::::::::::::::::::::::::"<<endl<<endl; 

    double num; 
    while(true) 
    { 
     cout << ">>"; 
     cin >> input; 

     if(istringstream(input) >> num) 
     { 
      stack.push(num); 
     } 
     else if (isOperator(input)) 
     { 
      performOp(input, stack); 
     } 
     else if (input == ".") 
     { 
      stack.print(); 
      double val = stack.tip(); 
      cout << "= " << val << endl << ">>"; 
     } 
     else if (input == "q") 
     { 
      return 0; 
     } 
     else 
     { 
      cout << "Error: Invalid input" << endl; 
     } 
    } 
} 

Я также очищены несколько других ошибок.

+0

'* +' не проблема. '+' здесь просто унарный плюс. – Simon

+0

Спасибо! Оцените ответ. – Tyler

Смежные вопросы