Search code examples
c++expressionreversepolish

Printing individual operations from a postfix expression string in C++


Wanting help with breaking apart postfix expressions and outputting each individual operation. My issue is NOT evaluating the actual expression, but rather printing each individual operation before evaluating.

I am using C++ to write a program that evaluates postfix expressions. The types of expressions that will be taken in are in infix notation, and use capital letters (A-Z) and these four operations: *, /, +, and -.

An example of this would be: (A + B) * (F - G)

I have written a function that changes infix to postfix:

AB+FG-*

Now I would like to write a function that outputs each individual operation. For the example above, it would look something like this:

Operations:

AB+

FG-

AB+FG-*

It would need to output the operations in order of precedence. Since A and B are in parentheses, they would need to be done first, and so on. I have tried to write a function that takes a postfix expression as input and returns nothing. The function creates a stack of type char and loops through the expression from beginning to end.

If the character is an operand, it is pushed to the stack. If the character is an operator, the two top values of the stack are stored in char variables and then outputted with their respective operator.

However, my function does not seem to be outputting the operations correctly.

#include<iostream>
#include<stack>
#include <algorithm> 
#include <cstdlib>
#include<string>

void operations(string exprsn) {

char op1, op2;
int len, x, j = 0;
len = exprsn.length();
stack<char>s;
string ns;

for (int i = 0; i < len; i++) {

    if (exprsn[i] >= 'A' && exprsn[i] <= 'Z') {
        s.push(exprsn[i]);
    }

    else if (isOperator(exprsn[i])) {
        op1 = s.top();
        s.pop();
        op2 = s.top();
        s.pop();
        switch (exprsn[i]) {
        case '+':
            s.push(op2 + op1 + '+' );
            cout << op2 << op1 << "+\n";
            break;
        case '-':
            s.push(op2 + op1 + '-');
            cout << op2 << op1 << "-\n";
            break;
        case '*':
            s.push(op2 + op1 + '*');
            cout << op2 << op1 << "*\n";
            break;
        case '/':
            s.push(op2 + op1 + '/');
            cout << op2 << op1 << "/\n";
            break;
        }

        }


    }
}

int main(){
string s = "AB+CD-*";
operations(s);
return 0;
}

Expected output:

AB+

CD-

AB+CD-*

Actual output:

AB+

CD-

«┤*

I am not sure what's happening with the last line, but I think it has something to do with the way I am pushing the characters into the stack.

Here is another example:

Infix expression: ( A + B ) / C + ( D - E ) * F * ( G - H )

After being converted to postfix notation:

AB+C/DE-F*GH-*+

Expected output:

AB+

DE-

GH-

DE-F*

GH-*

AB+C/

AB+C/DE-F*GH-*+

Actual output:

AB+

«C/

DE-

╢F*

GH-

&╝*

+

I know I am going horribly wrong somewhere, and I am having difficulty understanding. Any help is greatly appreciated. Thank you.


Solution

  • The bug in the program comes from the s stack variable using type char and not type string, which is needed to store multiple characters.

    When op2 + op1 + '+' is pushed onto the stack, the + signs aren't concatentating the characters op2, op1, and '+' together, as all of the datatypes of each of the variables are characters. Rather, the + signs add up the ascii numerical value of each of the characters, resulting in strange output.

    Here is a fixed version of the code:

    void operations(string exprsn)
    {
    
        string op1, op2;
        int len, x, j = 0;
        len = exprsn.length();
        stack<string> s;
        string ns;
    
        for (int i = 0; i < len; i++)
        {
    
            if (exprsn[i] >= 'A' && exprsn[i] <= 'Z')
            {
                s.push(string(1, exprsn[i]));
            }
    
            else if (isOperator(exprsn[i]))
            {
                op1 = s.top();
                s.pop();
                op2 = s.top();
                s.pop();
                switch (exprsn[i])
                {
                case '+':
                    s.push(op2 + op1 + '+');
                    cout << op2 << op1 << "+\n";
                    break;
                case '-':
                    s.push(op2 + op1 + '-');
                    cout << op2 << op1 << "-\n";
                    break;
                case '*':
                    s.push(op2 + op1 + '*');
                    cout << op2 << op1 << "*\n";
                    break;
                case '/':
                    s.push(op2 + op1 + '/');
                    cout << op2 << op1 << "/\n";
                    break;
                }
            }
        }
    }
    
    int main()
    {
        string s = "AB+CD-*";
        operations(s);
        return 0;
    }