0

im work this assignment and keep getting Exception in thread "main" java.lang.RuntimeException: Stack Underflow at Stack.pop(Postfix.java:74) at Postfix.eval(Postfix.java:221)at Postfix.main(Postfix.java:112)

dont know why i look at the stack and write it correct , i cant see problem why it pop when (3*4)/5

import java.io.IOException;
class  CharStack
{
    private final int STACKSIZE= 80;
    private int top;
    private char[] items;

    public CharStack(){
          items = new char[STACKSIZE];
          top =-1;

    }

    public boolean empty() {

        if(top==-1){
               return true;
           }


               return false;

    }

    public char pop() {
         if(empty()){
             throw new RuntimeException("Stack Underflow");
          }
     return items[top--];

    }

    public void push(char symb) 
    {
        if(top == STACKSIZE -1) {
            throw new RuntimeException("Stack Overflow");
       }
      items[++top] =symb;


    }

    public char peek() {
           if(empty()){
                throw new RuntimeException("Stack Underflow");
            }
           return items[top];
    }
    }
class Stack {
    private final int STACKSIZE= 80;
    private int top;
    private double[] items;

    public Stack(){
          items = new double[STACKSIZE];
          top =-1;

    }
    public void push(double x) 
    {
        if(top == STACKSIZE -1) {
               throw new RuntimeException("Stack Overflow");
          }
         items[++top] =x;



    }

    public double pop(){
        if(empty()){
             System.out.print(top);
            throw new RuntimeException("Stack Underflow");
         }
    return items[top--];

   }

    public double peek()  {
           if(empty()){

                throw new RuntimeException("Stack Underflow");
            }
           return items[top];


    }
   boolean empty()
   {
       if(top==-1){
           return true;
       }

           return false;


   }
}
public class Postfix {

     public final static int MAXCOLS = 80;

    public static void main(String[] args) throws IOException {

        String infix, pfix;
        System.out.println("Enter a infix  String: ");
        infix = readString().trim();
        System.out.println("The original infix expr is:  " + infix);
        pfix = postfix(infix);
        System.out.println("The Postfix expr is:  " + pfix);
        System.out.println("The value is :  " + eval(pfix));
    } // end main


    public static boolean isOperand(char x) 
    {
        if(x == '+')
        {
            return false;
        }
        else if(x == '-')
        {
            return false;
        }
        else if (x == '*')
        {
            return false;
        }
        else if (x ==  '/')
        {
            return false;
        }
        else if ( x== '$')
        {
            return false;
        }

        return true;

    }


    public static int operPrecedence(char oper) 
    {
        if(oper == '+'||oper == '-' )       
        {
            return 1;
        }

        else if (oper == '*' || oper ==  '/')
        {
            return 2;
        }

        else if (oper == '$')
        {
            return 3;
        }
        return 0;

    }


    public static boolean precedence(char top, char symb) 
    {

        if ((top != '('||top != ')')&&symb == '(')
        {
            return false;
        }
        if (top == '(' && (symb != '('||symb != ')') )
        {
            return false;
        }

        else if((top != '('||top != ')')&&symb ==')' )
        {
            return true;
        }
         int opcode1, opcode2;
         opcode1 =operPrecedence(top) ;
         opcode2 =operPrecedence(symb) ;

        if(opcode1>=opcode2){
            return true;
        }
            return false;

        }


    public static String readString() throws IOException {
        char[] charArray = new char[80];
        int position = 0;
        char c;
        while ((c = (char) System.in.read()) != '\n') {
            charArray[position++] = c;

        }
        return String.copyValueOf(charArray, 0, position); // turns a character array into a string, starting between zero and position-1

    }// end read string

    public static double eval(String infix) {

        char c;
        int position;
        double opnd1, opnd2, value;
        Stack opndstk = new Stack();
        for (position = 0; position < infix.length(); position++) {
            c = infix.charAt(position);
            if (Character.isDigit(c)) // operand-convert the character represent  of  
            // the digit into double and push it into the
            // stack
            {
                opndstk.push((double) Character.digit(c, 10));
            } else {

                // operator
                opnd2 = opndstk.pop();
                opnd1 = opndstk.pop();
                value = oper(c, opnd1, opnd2);
                opndstk.push(value);
            } // else
        } // end for
        return opndstk.pop();
    }// end eval

    public static String postfix(String infix) {
        int position, outpos = 0;
        char symb;
        char[] postr = new char[MAXCOLS];
        CharStack opstk = new CharStack();
        for (position = 0; position < infix.length(); position++) {
            symb = infix.charAt(position);
            if (isOperand(symb)) {
                postr[outpos++] = symb;
            } else {
                while (!opstk.empty() && precedence(opstk.peek(), symb)) {
                    postr[outpos++] = opstk.pop();
                } // end while
                if (symb != ')') {
                    opstk.push(symb);
                } else {
                    opstk.pop();
                }
            } // end else

        } // end for
        while (!opstk.empty()) {
            postr[outpos++] = opstk.pop();
        }
        return String.copyValueOf(postr, 0, outpos);

    }// end pos

    public static double oper(char symb, double op1, double op2) {

        double value = 0;
        switch (symb) {
            case '+':
                value = op1 + op2;
                break;
            case '-':
                value = op1 - op2;
                break;
            case '*':
                value = op1 * op2;
                break;
            case '/':
                value = op1 / op2;
                break;
            case '$':
                value = Math.pow(op1, op2);
                break;
            default:
                throw new RuntimeException("illegal operator: " + symb);

        }// end switch
        return value;
    }// end oper

}
tommy
  • 11
  • 1
  • 5
  • 7
    You've posted nearly 300 lines of code. Please do appropriate diagnostic research to reduce this to a [mcve]. – Jon Skeet Jan 28 '16 at 21:02
  • I'm not sure if you knew his already, but there is a [`Stack`](https://docs.oracle.com/javase/8/docs/api/java/util/Stack.html) class that you can use – ricky3350 Jan 28 '16 at 21:05
  • @ricky3350 A better option is the [`ArrayDeque`](http://docs.oracle.com/javase/8/docs/api/java/util/ArrayDeque.html) class. – TNT Jan 28 '16 at 21:07
  • @TNT Is there some sort of advantage to it? I've never used it before. – ricky3350 Jan 28 '16 at 21:08
  • i know their is a Stack class in java but this assignment requirement me to use a array as stack – tommy Jan 28 '16 at 21:12
  • 1
    @ricky3350 [This SO question](http://stackoverflow.com/questions/12524826/why-should-i-use-deque-over-stack) explains a few reasons. Also, read what's in the link that you posted and you'll find: *"A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class."* – TNT Jan 28 '16 at 21:13
  • @TNT I see, thank you. – ricky3350 Jan 28 '16 at 21:24

1 Answers1

0

At least part of the problem you're having is your isOperand method. The characters ( and ) are not operands, however, when they are passed to this method, it would return true. For a quick test, I added the following lines to the end of the method:

else if (x == '(')
{
    return true;
}
else if (x == ')')
{
    return true;
}

And your example input, (3*4)/5) runs successfully. However, this breaks your postfix output, as it leaves the brackets out of the postfix version and instead prints 34*5/, which I am guessing you don't want.

Then, I looked at your eval method, which is where the problem is coming from, according to the error message I'm receiving:

Exception in thread "main" java.lang.RuntimeException: Stack Underflow
    at Stack.pop(Postfix.java:74)
    at Postfix.eval(Postfix.java:221)
    at Postfix.main(Postfix.java:112)

Note the line Postfix.java:221, which indicates the line that called the method which created the error. If you output your character c right before that line is called, you'll notice that c is the ( character, which means your eval method is recognizing ( as an operator, and is attempting to pop two operands after it, causing your underflow.

All of this is fairly simple to determine with some System.out.println() calls, and looking at your error. I'll leave the actual fixing to you, but at least you've hopefully got a direction to head in now.

Joseph Roque
  • 5,066
  • 3
  • 16
  • 22