1

Here is a java class I had to make for my data structures class. I know that this is far from the best way to do the conversion, but it is off of the pseudo code he gave in class and is therefor what he is looking for. The only thing he left for us to figure out on our own was for how the algorithm recognizes parenthesis. The program runs just fine when I input an expression without them, but the minute I add parenthesis the program won't run, specifically, through some debugging, I found that the close parenthesis does this ")". I marked with comments where the actual parenthesis part of the method is. Thanks for the help!

public class InToPost {
    private Stack theStack;
    private String infix;
    private String postfix = "";

    public InToPost(String in) {
        infix = in;
        int stackSize = infix.length();
        theStack = new Stack(stackSize);
    }

    public String convert(){
        for (int i = 0; i < infix.length(); i++) {
            char ch = infix.charAt(i);
            if ((ch == '0') || (ch == '1') || (ch == '2') || (ch == '3') || (ch == '4') ||
                (ch == '5') || (ch == '6') || (ch == '7') || (ch == '8') || (ch == '9')) {
                postfix = postfix + ch;
            }
            //check for parenthesis
            else if (ch == ')'){
                while (theStack.topStk() != '('){
                    int topStk = theStack.pop();
                    postfix = postfix + topStk;
                }
                theStack.pop();
            } else {
                while ((theStack.isEmpty() == false)&&(prcd(theStack.topStk(),ch) == true)){
                    char topSymb = theStack.pop();
                    postfix = postfix + topSymb;
                }
                theStack.push(ch);
            }
        }
        while(theStack.isEmpty() == false){
            char topSymb = theStack.pop();
            postfix = postfix + topSymb;
        }
        return postfix;
    }

    public boolean prcd(char one, char two){
        int onePrcd = 0;
        int twoPrcd = 0;
        if ((one == '+') || (one == '-')){
            onePrcd = 1;
        }
        if ((two == '+') || (two == '-')){
            twoPrcd = 1;
        }
        if ((one == '*') || (one == '/')){
            onePrcd = 2;
        }
        if ((two == '*') || (two == '/')){
            twoPrcd = 2;
        }
        if (one == '$') {
            onePrcd = 3;
        }
        if (two == '$') {
            twoPrcd = 3;
        }
        if (one == '(') {
            onePrcd = 4;
        }
        if (two == '('){
            twoPrcd = 4;
        }
        if (onePrcd >= twoPrcd){
            return true;
        } else {
            return false;
        }
    }
    public static void main(String[] args){
        String input = "(2+3)*4";
        String output;
        InToPost theTrans = new InToPost(input);
        output = theTrans.convert(); 
        System.out.println("Postfix is " + output + '\n');
    }  
}
Manishearth
  • 14,882
  • 8
  • 59
  • 76
Nclay09
  • 51
  • 2
  • 5
  • 1
    "((ch == '0') || (ch == '1') || (ch == '2') || (ch == '3') || (ch == '4') || (ch == '5') || (ch == '6') || (ch == '7') || (ch == '8') || (ch == '9')) ..." -- I seriously hope you can think of a smarter way to write this expression... – Michael Nett Oct 06 '11 at 07:16
  • 1
    Not sure where the problem is, but this line: `while (theStack.topStk() != '('){` can be reached even when the stack is empty. You'll want to take care of that situation. – S.L. Barth is on codidact.com Oct 06 '11 at 08:38
  • 1
    Changed the number part to Character.isDigit(ch). Admittedly stupid on my part. Also fixed this line: else if ((ch == ')') && (!theStack.isEmpty())) – Nclay09 Oct 06 '11 at 15:27
  • The problem is: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1 at Stack.topStk(Stack.java:18) at InToPost.convert(InToPost.java:23) at InToPost.main(InToPost.java:82) – Nclay09 Oct 06 '11 at 15:27

1 Answers1

2

This was a fun exercise. You were pretty close but there are some bugs in here. I had to debug the code and twiddle a bit.

  1. As @S.L. Barth mentioned, the while (theStack.topStk() != '('){ line can cause a stack underflow. You'll need to change this to be:

    while (!theStack.isEmpty() && theStack.topStk() != '('){
  2. You'll also need to protect the theStack.pop(); right below there:

    if (!theStack.isEmpty()) {
        theStack.pop();
    }
    
  3. When you are checking the precedence from the top of the stack, you shouldn't put '(' characters on the output:

    if (topSymb != '(') {
        postfix = postfix + topSymb;
    }
    
  4. But the kicker bug is that you are unloading from the stack into an int when you are closing the ')': int topStk = theStack.pop(); That should be changed to a char which outputs a + instead of 43. :-)

Couple of style points:

  • As mentioned, use Character.isDigit(ch)
  • You should use a StringBuilder() so you can do postfix.append(ch) instead of building the string with many postfix + ch. [Shudder]
  • I'd make the postfix field local to the convert() method to reduce scope.
  • It's considered bad form to say == false or == true. Just drop the == true and use the ! character for false: (!theStack.isEmpty()) && prcd(theStack.topStk(),ch)
  • I'd create a charToPrecedence(char) which uses a switch to return the value of each char. Much cleaner code.

    public boolean precident(char one, char two) {
        return (charToPrcd(one) >= charToPrcd(two));
    }
    private int charToPrcd(char ch) {
        switch (ch) {
            case '+' : case '-' : return 1;
            case '*' : case '/' : return 2;
            case '$' : return 3;
            case '(' : return 4;
            default : return 0;
        }
    }
    
Gray
  • 115,027
  • 24
  • 293
  • 354
  • 1
    @Gary Thank you for the help and the style points. But, program is still not working. I don't know if I was exactly following your recommendations, but this is what I tried: else if ((ch == ')') && (!theStack.isEmpty())){ while (theStack.topStk() != '('){ char topSymb = theStack.pop(); if (topSymb != '(') { postfix = postfix + topSymb; } } if (!theStack.isEmpty()) { theStack.pop(); } } – Nclay09 Oct 06 '11 at 17:51
  • Here's the code that's working for me @user981445. http://pastie.org/2650927 – Gray Oct 06 '11 at 18:06