Plantage de la calculatrice Java avec entrée de parenthèses


Aidez-moi stackoverflow, vous êtes mon seul espoir. J'ai essayé de faire une calculatrice simple, et finalement je l'ai fait FONCTIONNER! Le problème est que seules les expressions simples sont évaluées. Par exemple: 4*5 donnerait 20.0. (Génial!)

Chaque fois que je lui donne une expression plus compliquée comme 4*(2+3), le programme se bloque en raison d'une EmptyStackException. Je comprends l'exception, mais je suis incapable de recréer le problème dans mon esprit lorsque je parcourt le code manuellement avec mon cerveau et une feuille de papier.

Quelqu'un peut-il comprendre pourquoi il s'écrase? Voici le code complet. J'ai marqué l'endroit où le code se bloque avec des mots en gras et en majuscules. (c'est-à-dire QUE LE PROGRAMME SE BLOQUE ICI)

/**
 * Human
 * Project 3: SUPER-DUPER JAVA CALCULATOR
 */

import java.util.*;
import java.util.Stack;
import java.lang.String;
import java.util.ArrayList;
import java.lang.StringBuilder;
import java.util.HashSet;
import java.lang.Exception;
import java.lang.Math;

public class InfixEvaluator {

    public static class SyntaxErrorException extends Exception {
        /**
         * Construct a SyntaxErrorException with the specified message.
         *
         * @param message The message
         */
        SyntaxErrorException(String message) {
            super(message);
        }
    }

    /**
     * This is the stack of operands:
     * i.e. (doubles/parentheses/brackets/curly braces)
     */
    private static Stack<Double> operandStack = new Stack<Double>();

    /**
     * This is the operator stack
     * i.e. (+-/*%^)
     */
    private static Stack<String> operatorStack = new Stack<String>();

    /**
     * These are the possible operators
     */
    private static final String OPERATORS = "+-/*%^()[]{}";
    private static final String BRACES = "()[]{}";
    private static final String NONBRACES = "+-/*%^";
    private static final int[] PRECEDENCE = {1, 1, 2, 2, 2, -1, -1, -1, -1, -1, -1};
    /**
     * This is an ArrayList of all the discrete
     * things (operators/operands) making up an input.
     * This is really just getting rid of the spaces,
     * and dividing up the "stuff" into manageable pieces.
     */
    static ArrayList<String> input = new ArrayList<String>();

    public static ArrayList inputCleaner(String postfix) {
        StringBuilder sb = new StringBuilder();
        String noSpaces = postfix.replace(" ", "");
        try {
            for (int i = 0; i < noSpaces.length(); i++) {
                char c = noSpaces.charAt(i);
                boolean isNum = (c >= '0' && c <= '9');

                if (isNum) {
                    sb.append(c);
                    if (i == noSpaces.length() - 1) {
                        input.add(sb.toString());
                        sb.delete(0, sb.length());
                    }
                } else if (c == '.') {
                    for (int j = 0; j < sb.length(); j++) {
                        if (sb.charAt(j) == '.') {
                            throw new SyntaxErrorException("You can't have two decimals in a number.");
                        } else if (j == sb.length() - 1) {
                            sb.append(c);
                            j = (sb.length() + 1);
                        }
                    }
                    if (sb.length() == 0) {
                        sb.append(c);
                    }
                    if (i == noSpaces.length() - 1) {
                        throw new SyntaxErrorException("You can't end your equation with a decimal!");
                    }
                } else if (OPERATORS.indexOf(c) != -1) {
                    if (sb.length() != 0) {
                        input.add(sb.toString());
                        sb.delete(0, sb.length());
                    }
                    sb.append(c);
                    input.add(sb.toString());
                    sb.delete(0, sb.length());
                } else {
                    throw new SyntaxErrorException("Make sure your input only contains numbers, operators, or parantheses/brackets/braces.");
                }
            }

            int numLP = 0;
            int numRP = 0;
            int numLB = 0;
            int numRB = 0;
            int numLBr = 0;
            int numRBr = 0;

            for (int f = 0; f < input.size(); f++) {
                String trololol = input.get(f);

                switch (trololol) {
                    case "(":
                        numLP++;
                        break;
                    case "[":
                        numLB++;
                        break;
                    case "{":
                        numLBr++;
                        break;
                    case ")":
                        numRP++;
                        break;
                    case "]":
                        numRB++;
                        break;
                    case "}":
                        numRBr++;
                        break;
                    default: //do nothing
                        break;
                }

            }
            if (numLP != numRP || numLB != numRB || numLBr != numRBr) {
                throw new SyntaxErrorException("The number of brackets, braces, or parentheses don't match up!");
            }

            int doop = 0;
            int scoop = 0;
            int foop = 0;
            for (int f = 0; f < input.size(); f++) {
                String awesome = input.get(f);
                switch (awesome) {
                    case "(":
                        doop++;
                        break;
                    case "[":
                        scoop++;
                        break;
                    case "{":
                        foop++;
                        break;
                    case ")":
                        doop--;
                        break;
                    case "]":
                        scoop--;
                        break;
                    case "}":
                        foop--;
                        break;
                    default: //do nothing
                        break;
                }
                if (doop < 0 || scoop < 0 || foop < 0) {
                    throw new SyntaxErrorException("The order of your parentheses, brackets, or braces is off.\nMake sure you open a set of parenthesis/brackets/braces before you close them.");
                }
            }
            if (NONBRACES.indexOf(input.get(input.size() - 1)) != -1) {
                throw new SyntaxErrorException("The input can't end in an operator");
            }
            return input;
        } catch (SyntaxErrorException ex) {
            System.out.println(ex);
            return input;
        }
    }

    /**
     * Method to process operators
     *
     * @param op The operator
     * @throws EmptyStackException
     */
    private static void processOperator(String op) {
        if (operatorStack.empty() || op == "(" || op == "[" || op == "{") {
            operatorStack.push(op);
        } else {
            //peek the operator stack and
            //let topOp be the top operator.
            String topOp = operatorStack.peek();
            if (precedence(op) > precedence(topOp)) {
                operatorStack.push(op);
            } else {
                //Pop all stacked operators with equal
                // or higher precedence than op.
                while (!operatorStack.empty() && precedence(op) <= precedence(topOp)) {
                    double r = operandStack.pop();
                    double l = operandStack.pop();
                    String work = operatorStack.pop();
                    switch (work) {
                        case "+":
                            operandStack.push(l + r);
                            break;
                        case "-":
                            operandStack.push(l - r);
                            break;
                        case "*":
                            operandStack.push(l * r);
                            break;
                        case "/":
                            operandStack.push(l / r);
                            break;
                        case "%":
                            operandStack.push(l % r);
                            break;
                        case "^":
                            operandStack.push(Math.pow(l, r));
                            break;
                        default: //do nothing, but this should never happen
                            break;
                    }

                    if (topOp == "(" || topOp == "[" || topOp == "{") {
                        //matching '(' popped - exit loop.
                        operandStack.push(l);
                        operandStack.push(r);
                        break;
                    }

                    if (!operatorStack.empty()) {
                        //reset topOp
                        topOp = operatorStack.peek();
                    }
                }

                //assert: Operator stack is empty or
                // current operator precedence > top of stack operator precedence.
                if (op != ")" || op != "]" || op != "}") {
                    operatorStack.push(op);
                }
            }
        }
    }

    public static String infixCalculator(ArrayList<String> puke) {
        int p;
        for (p = 0; p < puke.size(); p++) {
            if (OPERATORS.indexOf(puke.get(p)) == -1) {
                double herp = Double.parseDouble(puke.get(p));
                operandStack.push(herp);
            } else {
                processOperator(puke.get(p));
            }
        }
        if (p == puke.size()) {
            while (!operatorStack.empty()) {
                double r = operandStack.pop();
                double l = operandStack.pop();
                String work = operatorStack.pop();
                switch (work) {
                    case "+":
                        operandStack.push(l + r);
                        break;
                    case "-":
                        operandStack.push(l - r);
                        break;
                    case "*":
                        operandStack.push(l * r);
                        break;
                    case "/":
                        operandStack.push(l / r);
                        break;
                    case "%":
                        operandStack.push(l % r);
                        break;
                    case "^":
                        operandStack.push(Math.pow(l, r));
                        break;
                    default:
                        break;
                }
            }
        }
        return String.valueOf(operandStack.pop());
    }

    private static int precedence(String op) {
        return PRECEDENCE[OPERATORS.indexOf(op)];
    }

    public static void main(String[] args) {

        do {
            try {
                ArrayList test = new ArrayList();
                Scanner f = new Scanner(System.in);


                System.out.println("Please insert an argument: \n");


                String g = f.nextLine();

                test = inputCleaner(g);

                for (int z = 0; z < test.size(); z++) {
                    System.out.println(test.get(z));
                }

                System.out.println(infixCalculator(test));

                test.clear();
            } catch (EmptyStackException e) {
                System.out.println("Make sure you only put in operators and operands.");
            }
        } while (true);
    }
}

Trace de pile:

java.util.EmptyStackException at 
    java.util.Stack.peek(Stack.java:102) at
    java.util.Stack.pop(Stack.java:84) at 
    InfixEvaluator.processOperator(InfixEvaluator.java:177) at 
    InfixEvaluator.infixCalculator(InfixEvaluator.java:225) at 
    InfixEvaluator.main(InfixEvaluator.java:276) 
Author: FelixTheNub, 2014-05-06

2 answers

Votre erreur vient de poping un élément hors de la pile lorsque la pile est vide. D'où le nom EmptyStackException.

J'ai remarqué dans vos boucles que vous dites quelque chose comme while(!operatorStack.empty()) mais à l'intérieur de la boucle while, vous sortez 2 ou parfois 3 éléments de la pile. Si vous souhaitez supprimer plus d'éléments d'un tableau qu'un, vous devez le tester dans votre boucle while.

Donc, si vous désactivez 2 éléments, faites while (operatorStack.size() > 2 ). J'ai modifié votre code en changeant toutes vos boucles while pour être correct et cela a bien fonctionné pour ces entrées

(2+3) et (2+3)+5

Voici ce que j'ai fait:

  • A déplacé le code standard dans de nouvelles méthodes
  • Ajout de signatures de méthode commentaires
  • Correction de la priorité de votre opérateur, l'opérateur pow avait la mauvaise priorité.
  • Comparaison de chaînes modifiée dans un tas d'endroits de str1 == str2 à str1.equals(str2). Vous devriez regarder Comment comparer les chaînes en Java? pour voir pourquoi j'ai fait ça.
  • Ajouté dans les instructions System.out.println pour déboguer votre application. Je les ai laissés pour que vous puissiez voir la sortie et la vérifier par vous-même. Vous devriez regarder à travers et voir ce que j'ai fait pour vous aider à déboguer à l'avenir.

import java.util.*;
import java.util.Stack;
import java.lang.String;
import java.util.ArrayList;
import java.lang.StringBuilder;
import java.util.HashSet;
import java.lang.Exception;
import java.lang.Math;

public class InfixEvaluator
{

     public static class SyntaxErrorException extends Exception {
        /** Construct a SyntaxErrorException with the specified message.
           @param message The message
           */
        SyntaxErrorException(String message) {
            super(message);
        }
    }
    /** This is the stack of operands:
       i.e. (doubles/parentheses/brackets/curly braces)
    */
    private static Stack<Double> operandStack = new Stack<Double>();

    /** This is the operator stack
     *  i.e. (+-/*%^)
     */
    private static Stack<String> operatorStack = new Stack<String>();

    /** These are the possible operators */
    private static final String OPERATORS = "+-/*%^()[]{}";
    private static final String BRACES = "()[]{}";
    private static final String NONBRACES = "+-/*%^";
    //                                       +  -  /  *  %   ^  (   )   [   ]   {   }
    private static final int[] PRECEDENCE = {1, 1, 2, 2, 3, 3, -1, -1, -1, -1, -1, -1};
    /** This is an ArrayList of all the discrete
        things (operators/operands) making up an input.
        This is really just getting rid of the spaces,
        and dividing up the "stuff" into manageable pieces.
       */
    static ArrayList<String> input = new ArrayList<String>();

    /**
     * TODO: write this
     * @param postfix
     * @return
     */
    public static ArrayList inputCleaner(String postfix){
      StringBuilder sb = new StringBuilder();
      String noSpaces = postfix.replace(" ", "");
      try {
        for (int i = 0; i < noSpaces.length(); i++) {
            char c = noSpaces.charAt(i);
            boolean isNum = (c >= '0' && c <= '9');

            if (isNum) {
                sb.append(c);
                if (i == noSpaces.length()-1) {
                    input.add(sb.toString());
                    sb.delete(0, sb.length());
                }
            } else if (c == '.') {
                for (int j = 0; j < sb.length(); j++) {
                    if (sb.charAt(j) == '.') {
                        throw new SyntaxErrorException("You can't have two decimals in a number.");
                    } else if (j == sb.length() - 1) {
                        sb.append(c);
                        j = (sb.length() + 1);
                    } 
                } 
                if (sb.length() == 0) {
                    sb.append(c);
                }
                if (i == noSpaces.length()-1) {
                    throw new SyntaxErrorException("You can't end your equation with a decimal!");
                }
            } else if (OPERATORS.indexOf(c)!= -1) {
                if (sb.length() != 0) {
                    input.add(sb.toString());
                    sb.delete(0, sb.length()); 
                }
                sb.append(c);
                input.add(sb.toString());
                sb.delete(0, sb.length());
            } else {
                throw new SyntaxErrorException("Make sure your input only contains numbers, operators, or parantheses/brackets/braces.");
            }
        }

        int numLP = 0;
        int numRP = 0;
        int numLB = 0;
        int numRB = 0;
        int numLBr = 0;
        int numRBr = 0;

        for (int f = 0; f < input.size(); f++) {
            switch (input.get(f)) {
                case "(": numLP++;
                    break;
                case "[": numLB++;
                    break;
                case "{": numLBr++;
                    break;
                case ")": numRP++;
                    break;
                case "]": numRB++;
                    break;
                case "}": numRBr++;
                    break;
                default: //do nothing
                    break;
            }

        }
        if (numLP != numRP || numLB != numRB || numLBr != numRBr) {
            throw new SyntaxErrorException("The number of brackets, braces, or parentheses don't match up!");
        }

        int doop = 0;
        int scoop = 0;
        int foop = 0;
        for (int f = 0; f < input.size(); f++) {
            String awesome = input.get(f);
            switch (awesome) {
                case "(": doop++;
                    break;
                case "[": scoop++;
                    break;
                case "{": foop++;
                    break;
                case ")": doop--;
                    break;
                case "]": scoop--;
                    break;
                case "}": foop--;
                    break;
                default: //do nothing
                    break;
            }
            if (doop < 0 || scoop < 0 || foop < 0) {
                throw new SyntaxErrorException("The order of your parentheses, brackets, or braces is off.\nMake sure you open a set of parenthesis/brackets/braces before you close them.");
            }
        }
        if (NONBRACES.indexOf(input.get(input.size()-1)) != -1) {
            throw new SyntaxErrorException("The input can't end in an operator");
        }
        return input;
      } catch (SyntaxErrorException ex) {
            System.out.println(ex);
            return input;
      }
    }

     /**Method to process operators
     * @param op The operator
     * @throws SyntaxErrorException 
     * @throws EmptyStackException
     */
    private static void processOperator(String op) throws SyntaxErrorException {
        if (operatorStack.empty() || op.equals("(") || op.equals("[") || op.equals("{")) {
            operatorStack.push(op);
        } else {
            //peek the operator stack and
            //let topOp be the top operator.
            String topOp = operatorStack.peek();
            if (precedence(op) > precedence(topOp)) {
                topOp = op;
                operatorStack.push(op);
            } else {
                System.out.println(operatorStack);
                System.out.println(operandStack);
                System.out.println("--------------");
                //Pop all stacked operators with equal
                // or higher precedence than op.
                while (operandStack.size() >= 2 && !operatorStack.isEmpty()) {
                    double r = operandStack.pop();
                    double l = operandStack.pop();
                    String work = getNextNonBracerOperator();
                    System.out.println("L:" + l + " R:" + r + " W:" + work);

                    doOperandWork(work, l, r);

                    if(op.equals("(") || op.equals("[") || op.equals("{")) {
                        //matching '(' popped - exit loop.
                        operandStack.push(l);
                        operandStack.push(r);
                        break;
                    }

                    if (!operatorStack.empty()) {
                        //reset topOp
                        topOp = operatorStack.peek();
                    }
                }

                //assert: Operator stack is empty or
                // current operator precedence > top of stack operator precedence.
                if(!op.equals(")") || !op.equals("}") || !op.equals("}")) {
                    operatorStack.push(op);
                }
            }
        }
    }

    /**
     * TODO: write this
     * @param expressions
     * @return
     * @throws SyntaxErrorException
     */
    public static String infixCalculator(ArrayList<String> expressions) throws SyntaxErrorException {
        for (String expression : expressions) {
            if (OPERATORS.indexOf(expression) == -1) {
                operandStack.push(Double.parseDouble(expression));
            } else {
                processOperator(expression);
            } 
        } 
        while (operandStack.size() >= 2 && !operatorStack.isEmpty()) {
            System.out.println("--------------");
            System.out.println(operandStack);
            System.out.println(operatorStack);

            double r = operandStack.pop();
            double l = operandStack.pop();
            String work = getNextNonBracerOperator();
            System.out.println("L:" + l + " R:" + r + " W:" + work);

            doOperandWork(work, l, r);
        }
        if(operandStack.isEmpty())
            return null;
        return String.valueOf(operandStack.pop());
    }

    /**
     * goes through the stack and pops off all non operatable operations until it gets to one that is in the NONBRACES String
     * @return The next operatable string
     */
    private static String getNextNonBracerOperator() {
        String work = "\0"; // \0 is null, 
        while(!operatorStack.isEmpty() && NONBRACES.indexOf(work) == -1)
            work = operatorStack.pop();
        return work;
    }

    /**
     * 
     * @param work The operator you want to work. This really should be a character but its still a string
     * @param l Left side number
     * @param r Right side number
     * @throws SyntaxErrorException If the operator could not be found
     */
    private static void doOperandWork(String work, double l, double r) throws SyntaxErrorException {
        switch (work) {
            case "+": operandStack.push(l+r);
                break;
            case "-": operandStack.push(l-r);
                break;
            case "*": operandStack.push(l*r);
                break;
            case "/": operandStack.push(l/r);
                break;
            case "%": operandStack.push(l%r);
                break;
            case "^": operandStack.push(Math.pow(l, r));
                break;
            default: 
                throw new SyntaxErrorException("Invalid operand " + work);
        }
    }

    /**
     * @param op The operator
     * @return the precedence
     */
    private static int precedence(String op) {
        return PRECEDENCE[OPERATORS.indexOf(op)];
    }

    public static void main(String[] args) {
        try {
            ArrayList test = new ArrayList();
            Scanner f = new Scanner(System.in);

            //System.out.println("Please insert an argument: ");

            //String g = f.nextLine();
            //String g = "(1+1)^(3+1)";
            String g = "(1+3)*3^2+2*4-1";
            test = inputCleaner(g);

            for (int z = 0; z < test.size(); z++) {
                System.out.println(test.get(z));
            }

            System.out.println(infixCalculator(test));

            test.clear();
       } catch (SyntaxErrorException e) {
            System.out.println("Make sure you only put in operators and operands.");
            e.printStackTrace();
       }
    }
}
 2
Author: ug_, 2017-05-23 10:31:09

Vous essayez de comparer une chaîne avec ==. Utilisez plutôt String.equals(String)

if(!op.equals(")") || !op.equals("]") || !op.equals("}")) {
   operatorStack.push(op);
}

...

if (operatorStack.empty() || op.equals("(") || op.equals("[") || op.equals("{")) {
   operatorStack.push(op);
} else {

...

if (topOp.equals("(") || topOp.equals("[") || topOp.equals("(")) {
  //matching '(' popped - exit loop.
  operandStack.push(l);
  operandStack.push(r);
  break;
}

Ensuite, Si vous passez par votre code, vous verrez que vous essayez d'utiliser "(" comme un opérateur

Vous avez déjà poussé ")" sur la pile avant de vérifier. Vous devriez déplacer le contrôle.

if (precedence(op) > precedence(topOp)) {
   if(!op.equals(")") || !op.equals("]") || !op.equals("}")) {
     operatorStack.push(op);
   }
}

Code final

import java.util.*;

public class InfixEvaluator
{

    public static void main(String[] args) {
    ArrayList test = new ArrayList();
    Scanner f = new Scanner(System.in);


    System.out.println("Please insert an argument: \n");

    String g = f.nextLine();

    test = inputCleaner(g);

    for (int z = 0; z < test.size(); z++) {
        System.out.println(test.get(z));
    }

    System.out.println(infixCalculator(test));
}


 public static class SyntaxErrorException extends Exception {
    /** Construct a SyntaxErrorException with the specified message.
       @param message The message
       */
    SyntaxErrorException(String message) {
        super(message);
    }
}
/** This is the stack of operands:
   i.e. (doubles/parentheses/brackets/curly braces)
*/
private static Stack<Double> operandStack = new Stack<Double>();

/** This is the operator stack
 *  i.e. (+-/*%^)
 */
private static Stack<String> operatorStack = new Stack<String>();

/** These are the possible operators */
private static final String OPERATORS = "+-/*%^()[]{}";
private static final String BRACES = "()[]{}";
private static final String NONBRACES = "+-/*%^";
private static final int[] PRECEDENCE = {1, 1, 2, 2, 2, -1, -1, -1, -1, -1, -1};
/** This is an ArrayList of all the discrete
    things (operators/operands) making up an input.
    This is really just getting rid of the spaces,
    and dividing up the "stuff" into manageable pieces.
   */
static ArrayList<String> input = new ArrayList<String>();

public static ArrayList inputCleaner(String postfix){
  StringBuilder poop = new StringBuilder();
  String doody = postfix.replace(" ", "");
  try {
    for (int i = 0; i < doody.length(); i++) {
        char c = doody.charAt(i);
        boolean isNum = (c >= '0' && c <= '9');

        if (isNum) {
            poop.append(c);
            if (i == doody.length()-1) {
                input.add(poop.toString());
                poop.delete(0, poop.length());
            }
        } else if (c == '.') {
            for (int j = 0; j < poop.length(); j++) {
                if (poop.charAt(j) == '.') {
                    throw new SyntaxErrorException("You can't have two decimals in a number.");
                } else if (j == poop.length() - 1) {
                    poop.append(c);
                    j = (poop.length() + 1);
                } 
            } 
            if (poop.length() == 0) {
                poop.append(c);
            }
            if (i == doody.length()-1) {
                throw new SyntaxErrorException("You can't end your equation with a decimal!");
            }
        } else if (OPERATORS.indexOf(c)!= -1) {
            if (poop.length() != 0) {
                input.add(poop.toString());
                poop.delete(0, poop.length()); 
            }
            poop.append(c);
            input.add(poop.toString());
            poop.delete(0, poop.length());
        } else {
            throw new SyntaxErrorException("Make sure your input only contains numbers, operators, or parantheses/brackets/braces.");
        }
    }

    int numLP = 0;
    int numRP = 0;
    int numLB = 0;
    int numRB = 0;
    int numLBr = 0;
    int numRBr = 0;

    for (int f = 0; f < input.size(); f++) {
        String trololol = input.get(f);

        switch (trololol) {
            case "(": numLP++;
                break;
            case "[": numLB++;
                break;
            case "{": numLBr++;
                break;
            case ")": numRP++;
                break;
            case "]": numRB++;
                break;
            case "}": numRBr++;
                break;
            default: //do nothing
                break;
        }

    }
    if (numLP != numRP || numLB != numRB || numLBr != numRBr) {
        throw new SyntaxErrorException("The number of brackets, braces, or parentheses don't match up!");
    }

    int doop = 0;
    int scoop = 0;
    int foop = 0;
    for (int f = 0; f < input.size(); f++) {
        String awesome = input.get(f);
        switch (awesome) {
            case "(": doop++;
                break;
            case "[": scoop++;
                break;
            case "{": foop++;
                break;
            case ")": doop--;
                break;
            case "]": scoop--;
                break;
            case "}": foop--;
                break;
            default: //do nothing
                break;
        }
        if (doop < 0 || scoop < 0 || foop < 0) {
            throw new SyntaxErrorException("The order of your parentheses, brackets, or braces is off.\nMake sure you open a set of parenthesis/brackets/braces before you close them.");
        }
    }
    if (NONBRACES.indexOf(input.get(input.size()-1)) != -1) {
        throw new SyntaxErrorException("The input can't end in an operator");
    }
    return input;
  } catch (SyntaxErrorException ex) {
        System.out.println(ex);
        return input;
  }
}

 /**Method to process operators
 * @param op The operator
 * @throws EmptyStackException
 */
private static void processOperator(String op) {
    if (operatorStack.empty() || op.equals("(") || op.equals("[") || op.equals("{")) {
        operatorStack.push(op);
    } else {
        //peek the operator stack and
        //let topOp be the top operator.
        String topOp = operatorStack.peek();
        if (precedence(op) > precedence(topOp)) {
           if(!op.equals(")") || !op.equals("]") || !op.equals("}")) {
                operatorStack.push(op);
            }
        }
        else {
            //Pop all stacked operators with equal
            // or higher precedence than op.
            while (!operatorStack.empty() && precedence(op) <= precedence(topOp)) {
                double r = operandStack.pop();
                double l = operandStack.pop(); //***THE PROGRAM CRASHES HERE***
                String work = operatorStack.pop();
                switch (work) {
                    case "+": operandStack.push(l+r);
                        break;
                    case "-": operandStack.push(l-r);
                        break;
                    case "*": operandStack.push(l*r);
                        break;
                    case "/": operandStack.push(l/r);
                        break;
                    case "%": operandStack.push(l%r);
                        break;
                    case "^": operandStack.push(Math.pow(l, r));
                        break;
                    default: //do nothing, but this should never happen
                        break;
                }

                if (topOp.equals("(") || topOp.equals("[") || topOp.equals("(")) {
                    //matching '(' popped - exit loop.
                    operandStack.push(l);
                    operandStack.push(r);
                    break;
                }

                if (!operatorStack.empty()) {
                    //reset topOp
                    topOp = operatorStack.peek();
                }
            }

            //assert: Operator stack is empty or
            // current operator precedence > top of stack operator precedence.

        }
    }
}

public static String infixCalculator(ArrayList<String> puke) {
    int p;
    for (p = 0; p < puke.size(); p++) {
        if (OPERATORS.indexOf(puke.get(p)) == -1) {
            double herp = Double.parseDouble(puke.get(p));
            operandStack.push(herp);
        } else {
            processOperator(puke.get(p));
        } 
    } 
    if (p == puke.size()) {
        while (!operatorStack.empty()) {
                double r = operandStack.pop();
                double l = operandStack.pop();
                String work = operatorStack.pop();
                switch (work) {
                    case "+": operandStack.push(l+r);
                        break;
                    case "-": operandStack.push(l-r);
                        break;
                    case "*": operandStack.push(l*r);
                        break;
                    case "/": operandStack.push(l/r);
                        break;
                    case "%": operandStack.push(l%r);
                        break;
                    case "^": operandStack.push(Math.pow(l, r));
                        break;
                    default: //do nothing, but this should never happen
                        break;
                }
        }
    }
    return String.valueOf(operandStack.pop());
}

private static int precedence(String op) {
    return PRECEDENCE[OPERATORS.indexOf(op)];
}


}
 0
Author: SethB, 2014-05-06 05:13:25