문제

I need to create a RPN (postfix notation) calculator which makes simple operations (+, -, *, /), while using a linked list to maintain the stack. I have got the majority of it done but am running into a few problems. I can calculate any two numbers with one operand (ex: 5 5 + = 10), but cannot do anything more than that. I have done some research online, and watched a few YouTube videos to get where I am at now, but most use the stack reference to do it. I have tried to combine tutorials on that, along with how to make my own stack.

I am quite new to this and am pretty lost on how to calculate a larger expression (ex: 5 5 5 + + = 15), and I also need to check for errors, which I have completed some, but the ones I'm struggling with are "too many operators," and "too many operands." With too many operators I'm assuming it has something to do with not being able to pop off a value because there isn't one there, but that's as far as I can get (if it's right, still not quite sure how to implement it). Any help with any of these 3 things, or anything else you can see here would greatly be appreciated.

#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;
        }
    }
}
도움이 되었습니까?

해결책

First I would recommend you use std::map<double> instead of rolling your own linked list, unless it is for learning purposes.

The main problem is in SLLNode::popVal() and SLLNode::print() where things got a little bit confused.

Here is what you need to change to fix it:

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

There are many other things you could improve in your code but that should answer your question.

다른 팁

You have two operators, '*' and '+' in your expression to calculate multiplication. I have added & rearranged a bit of error checking,

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

Define a list node that contains head/tail, and counts the elements in your stack,

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

Your stack implementation leaks memory, allocates unnecessary nodes, and is missing a couple of useful stack operations that will help you solve some of your problems. You need a destructor that empties your list in case you forget to empty it, and it would help to have a print the entire list. Anyway,

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

You might want to add more operators, extract that,

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

Check your stacksize prior to extracting items from your stack,

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

You need some way to print your list. The forth language used ".", so here I have added a case to print the list using ".",

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

I also cleaned up a couple of other errors.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top