Search code examples
javastackinfix-notation

Evaluating infix expressions of unsigned integers using 2 stacks and getting wrong answer


I'm writing a program for class, that as the title says, evaluates infix expressions of unsigned integers using two stacks. The division should be integer division which is why the numbers are integers and not Double. I have created a GUI that gets input from the user and should return the answer. I have attached an ActionListener to the button to compute using this code:

result = Evaluate.evalExp(txtExp.getText());
            txtResult.setText(result + "");

The problem is that when I run the program I don't get the correct answer. For 3-4 I'll get 3, for 6/2 I get 2, and for anything that has parenthesis I get 0 for the answer. I have been trying to figure this out for the better part of the day without any results. I'm hoping someone here will be able to help.

import java.util.Stack;

public class Evaluate {

public static int evalExp(String input) {

    char[] tokens = input.toCharArray();

    Stack<Integer> number = new Stack<Integer>();
    Stack<Character> operator = new Stack<Character>();

    int holder = 0;
    int ans;

    for (int i=0; i < tokens.length; i++) { 
    // checking to see if token is a number
        if (tokens[i] >= '0' && tokens[i] <= '9') {
            StringBuffer num = new StringBuffer();
            // need to check if number is more than one digit long
            while ( i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
                num.append(tokens[i++]);
            number.push(Integer.parseInt(num.toString()));
        }
        else if (tokens[i] == '(')
            operator.push(tokens[i]);
        else if (tokens[i] == ')') {
            while (operator.peek() != '(') {
                holder = applyOp(operator.pop(), number.pop(), number.pop());
                number.push(holder);
            }
            operator.pop();
        }
        else if (tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '*' || tokens[i] == '/') {
            // check for precedence
            while (!operator.empty() && hasPrecedence(tokens[i], operator.peek())) {
                holder = applyOp(operator.pop(), number.pop(), number.pop());
                number.push(holder);
            }
            operator.push(tokens[i]);
        }   
    } // end for loop

    while (!operator.empty()) {
        holder = applyOp(operator.pop(), number.pop(), number.pop());
        number.push(holder);
    }
    ans = number.pop();
    return ans;

} // end of evalExp

// checks to see which operand has a higher precedence if any
public static boolean hasPrecedence(char op1, char op2) {
    if (op2 == '(' || op2 == ')')
        return false;
    if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
        return false;
    else
        return true;
} // end hasPrecedence


// return result of operator and operands
public static int applyOp(char op, int b, int a) {

    int ans = 0;

    switch (op) {
    case '+': ans = (a + b);
    //  return ans;
        break;
    case '-': ans = (a - b);
    //  return ans;
        break;
    case '*': ans = (a * b);
    //  return ans;
        break;
    case '/': ans = (a / b);
        if (b == 0)
            throw new ArithmeticException("Cannot divide by zero");
    //  return ans;
        break;
    }
    return ans;
} //end applyOp

} //end Class Evaluate


Solution

  • Debugging the same would have given you the answer.

                while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
                {
                    num.append(tokens[i++]);
                }
    

    In this code when you do i++, you have incremented the value of i but did not handle the char over there which is an operator in your use case.

                while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
                {
                    num.append(tokens[i++]);
                }
                if (i != tokens.length)
                    i--;
    

    Reverting the increment of the index fixes this issue. This may not be right solution. Just wanted to show the impact of the incremented index.