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

Problems Calculating a Postfix Expression with More Than Two Operands

本文关键字:后缀 操作数 表达式 问题 两个 计算      更新时间:2023-10-16

我需要创建一个RPN(后缀符号(计算器,它可以进行简单的操作(+,-,*,/(,同时使用链表来维护堆栈。 我已经完成了大部分工作,但遇到了一些问题。 我可以用一个操作数计算任意两个数字(例如:5 5 + = 10(,但不能做更多的事情。 我在网上做了一些研究,并观看了一些YouTube视频来达到我现在的位置,但大多数人使用堆栈引用来做到这一点。 我尝试结合这方面的教程,以及如何制作自己的堆栈。

我对此很陌生,并且对如何计算更大的表达式(例如:5 5 5 + + = 15(非常迷茫,我还需要检查错误,我已经完成了一些错误,但我正在努力解决的是"运算符太多"和"操作数太多"。 对于太多的运算符,我认为它与无法弹出值有关,因为那里没有值,但这是我所能得到的(如果它是正确的,仍然不太确定如何实现它(。 任何关于这 3 件事的帮助,或者您能在这里看到的任何其他内容,将不胜感激。

#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;
        }
    }
}
首先,

我建议您使用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 << ">>";
}

在代码中还有许多其他可以改进的地方,但这应该可以回答你的问题。

表达式

中有两个运算符"*"和"+"来计算乘法。 我添加并重新安排了一些错误检查,

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

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