0

我需要创建一个 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;
        }
    }
}
4

2 回答 2

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

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

于 2013-10-08T21:47:24.277 回答
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;
}

在从堆栈中提取项目之前检查您的堆栈大小,

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

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

于 2013-10-08T21:13:59.833 回答