计算具有两个以上操作数的后缀表达式的问题

时间:2013-10-08 20:59:30

标签: c++ stack postfix-notation rpn

我需要创建一个RPN(后缀表示法)计算器,它可以进行简单的操作(+, - ,*,/),同时使用链表来维护堆栈。我已经完成了大部分工作,但遇到了一些问题。我可以用一个操作数计算任意两个数字(例如: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;
        }
    }
}

2 个答案:

答案 0 :(得分: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 << ">>";
}

您可以在代码中改进许多其他内容,但这应该可以回答您的问题。

答案 1 :(得分:0)

你的表达式中有两个运算符'*'和'+'来计算乘法。我添加了&amp;重新安排了一些错误检查,

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;
}

定义包含head / tail的列表节点,并计算堆栈中的元素

#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;
        }
    }
}

我还清理了其他几个错误。