20 2 3 * + 2 8 * 5 + 4 * + here is my code..." /> 20 2 3 * + 2 8 * 5 + 4 * + here is my code..." /> 20 2 3 * + 2 8 * 5 + 4 * + here is my code..."/>

Infix to Postfix

869 views Asked by At

I am trying to convert infix to postfix.For example : "20 + 2 * 3 + (2*8 + 5)* 4" ->20 2 3 * + 2 8 * 5 + 4 * + here is my code :

Stack<Character> s = new Stack<Character>();
String postfix = "";
boolean enter = true;
String infixExpr = "20 + 2 * 3     + (2*8 + 5)* 4";

for(int i = 0;i<infixExpr.length();i++){

    if(Character.isDigit(infixExpr.charAt(i)) == true){
        postfix = postfix + infixExpr.charAt(i);
    }
    if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-'){
        if(s.isEmpty() == true){
            s.push(infixExpr.charAt(i));
        }
        else{
            if(s.peek() == '*' || s.peek() == '/' || s.peek() == '+' || s.peek() == '-'){
                while(s.isEmpty()== false){
                    postfix = postfix + s.pop();
                }
                s.push(infixExpr.charAt(i));
            }
            else{
                s.push(infixExpr.charAt(i));
            }
        }
    }
    if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ){
        if(s.isEmpty() == true){
            s.push(infixExpr.charAt(i));
        }
        else{
            if(s.peek()== '+' || s.peek() == '-' || s.peek() == '('){
                s.push(infixExpr.charAt(i));
            }
            else if(s.peek() == '*' || s.peek() == '/'){
                while(s.isEmpty()== false){
                    postfix = postfix + s.pop();
                }
                s.push(infixExpr.charAt(i));
            }
        }
        if(infixExpr.charAt(i) == '('){
            s.push(infixExpr.charAt(i));
        }
        if(infixExpr.charAt(i) == ')'){
            while(enter){

                if(s.peek() == '('){
                    enter = false;
                }
                else{
                    postfix = postfix + s.pop();
                }
            }
        }
    }
}

As it is written at the top I suppose to get "20 2 3 * + 2 8 * 5 + 4 * +" but I get "2023*+28*+54" which is wrong and I revised the code many times and still I cant see the problem. It would be great if anybody could help.

3

There are 3 answers

0
RealSkeptic On BEST ANSWER

Spaces

You are not putting any spaces on your postfix variable. You are only checking if the current character is one of the "interesting" characters (digits, operators), but not whether it's a space. As a result, if the current character is a space, you just skip it and you don't copy it to the postfix.

Since the only things that you put in the postfix are characters that you have checked, you end up with no spaces at all.

You can solve it like this:

  • Add a boolean called inNumber, set it to true at first.
  • Whenever you process a digit, before you add it to postfix, check if inNumber is true. If so, add a space first.
  • If you have just processed a digit, set inNumber to true.
  • If you are processing an operator, set inNumber to false.
  • Whenever you add any operator to the stack, add a space first.

The idea about this inNumber is that digits that all belong to the same number should not have spaces between them. But if the digit is added to postfix after we have processed an operator in the previous round, then it belongs to a new number, so there should be a space there.

So basically, your digit handling code should look like:

        if(Character.isDigit(infixExpr.charAt(i)) == true){
            if ( ! inNumber ) {
                postfix += " ";
            }
            postfix = postfix + infixExpr.charAt(i);
            inNumber = true;
        }

And in every if that indicate an operator you should have inNumber = false.

And every place where you add an operator to postfix should look like:

        postfix = postfix + " " + s.pop();

Handling parentheses

Your other problem is the handling of ().

First, you put the code that checks for ( and ) inside the if for * and /. Of course, if the character at the i position is * or /, it is not a ( or a ) so this code is never called.

So you should move the if for parentheses outside, to the same level of the if on numbers and operators.

Also, your use of enter is wrong. If you have parenthesis inside parenthesis, like ( 3 + ( 5 + 7 ) ), then at the first ) you will go back all the way to the parenthesis after the 5, which is OK. But then enter will become false and you will not process the external pair correctly. This is also true for (3 + 5 ) * ( 7 + 2 ) because you are not setting enter to true again after the beginning of the program.

Instead of using enter, you should pop what's on the stack and check if it was a (:

        if(infixExpr.charAt(i) == '('){
            inNumber = false;
            s.push(infixExpr.charAt(i));
        }
        if(infixExpr.charAt(i) == ')'){
            inNumber = false;
            char popped;
            while ( ( popped = s.pop() ) != '(' ) {
                    postfix = postfix + " " + popped;
            }
        }        

Unpopped operators

Finally, you finish when you completed scanning the input. But at this point you will still have operators waiting on the stack! You have to pop them all and add to postfix. So after the loop you should have:

    while ( ! s.isEmpty()) {
        postfix += " " + s.pop();
    }

Additional remarks:

  • It would be better and more clear if instead of using all those if statements, you used a switch statement.
  • There is no point in comparing a boolean expression to true. The proper way to write if (s.isEmpty() == true) is just if (s.isEmpty()), and instead of s.isEmpty() != true use ! s.isEmpty().
  • You are not doing any syntax checking. I am not sure if that's because this is homework, but in real life you should check that every ( is matched by a ), that every operator has two operands, and also handle negative numbers that may have a - in the beginning.
0
nLee On

The issue is that you are not adding spaces. You cannot, however, simply add a space in between each number. You have to make sure the spaces are not being added in between the digits of a whole number. To solve this, I simply added a postfix += " "; after the if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-')and again after if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ). The logic behind this is that once you encounter an operator, you know that everything before the operator was the number. Now when I run the program, the output is 20 2 3 *+2 8 *+5 4. There are still a few spaces that need to be added between the operators, but I'll let you handle that.

Modified code:

    if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-'){
        postfix += " ";

...

    if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ){
        postfix += " ";
2
bhavneet singh On

here is my code for your answer

#include<stack>
#include<iostream>
using namespace std;
bool high(char a,char b)
{
  if(b==' ')
    return true;
  else if(a==b)
    return false;
  else if(a=='/')
    return true;
  else if(a=='*'&&b!='/')
    return true;
  else if(b=='/')
    return false;
  else if(a!='/'&&b=='*')
    return false;
  else if(b=='-')
    return true;
  else if(a=='-'&&b!='(')
    return false;
  else if(b=='(')
    return true;
  else if(a=='(')
    return true;
  else if(a==')')
    return false;
}
main()
{
int k=0;
string s;
stack<char>s1;
s1.push(' ');
char ch;
while(cin>>ch)
{
    if(ch=='(')
    {
    k=1;
    s1.push(ch);}
    else if(ch>47&&ch<58)
    s.push_back(ch);
    else if(high(ch,s1.top()))
    s1.push(ch);
    else if(!high(ch,s1.top())&&ch!=')')
    {
        while(!s1.empty()&&!high(ch,s1.top()))
        {
            s.push_back(s1.top());
            s1.pop();
        }   
    s1.push(ch);}
    else if(ch==')')
    {
        while(!s1.empty()&&s1.top()!='(')
        {
            s.push_back(s1.top());
            s1.pop();
        }
        s1.pop();
        k=0;
    }

}
while(!s1.empty())
{
    s.push_back(s1.top());s1.pop();
}
cout<<s;
}