Explain postfix calculator in Java.
I made a postfix calculator in Java.
The code performs the functions I planned without problems, However, I'm not satisfied with it, because it's too verbose and I couldn't split it up into methods properly, especially PostfixCalculator.changeNotation().
Any help would be greatly appreciated.
Main.java
public class Main
{
public static void main(String[] args)
{
PostfixCalculator postCalc = new PostfixCalculator();
}
}
Stack.java (I didn't use the library because I'm studying data structures.)
import java.util.ArrayList;
import java.util.Scanner;
public class Stack
{
Scanner scan = null;
public ArrayListstack;
public Stack()
{
scan = new Scanner(System.in);
stack = new ArrayList(); }
public boolean isEmpty()
{
if (stack.size() == 0)
{
return true;
}
else
{
return false;
}
}
public void push(String element)
{
stack.add(element);
}
public void pop()
{
if(stack.isEmpty())
{
return;
}
else
{
stack.remove(stack.size()-1);
}
}
public int size()
{
return stack.size();
}
public String peek()
{
if (stack.isEmpty())
{
return null;
}
else
{
return stack.get(stack.size() - 1);
}
}
}
PostfixCalculator.java
import java.util.ArrayList;
import java.util.Scanner;
public class PostfixCalculator
{
String[] infixNotation = null;
String postfixNotation = "";
ArrayListaListPostfixNotation = null;
Scanner scan = null;
Stack stk = null;
public PostfixCalculator()
{
aListPostfixNotation = new ArrayList(); stk = new Stack();
scan = new Scanner(System.in);
String myInput = scan.nextLine();
infixNotation = myInput.split("",0);
postfixCalculate(changeNotation());
}
public String changeNotation() // Change the entered code from infix notation to postfix notation
{
for (int i = 0; i < infixNotation> {
if(infixNotation[i].equals(" "))
{
continue;
}
else if( !infixNotation[i].equals("+") && // when infixNotation[i] is operand
!infixNotation[i].equals("-") &&
!infixNotation[i].equals("*") &&
!infixNotation[i].equals("/") &&
!infixNotation[i].equals("(") &&
!infixNotation[i].equals(")") )
{
postfixNotation = postfixNotation + infixNotation[i];
}
else // when infixNotation[i] is operator or bracket
{
if(stk.isEmpty()) // It can push()ed, when stack is empty // Don't care ")~~~", because the ")" can't be first char
{
stk.push(infixNotation[i]);
}
else
{
if (infixNotation[i].equals("(")) // Just push() when it's '('
{
stk.push(infixNotation[i]);
}
else if (infixNotation[i].equals(")")) // When bracket is balanced (left and right), pop() a pair of bracket
{
stk.push(infixNotation[i]);
whenRightPush();
}
else // Have to the priority, when infixNotation[i] is operator
{
if (stk.peek().equals("("))
{
stk.push(infixNotation[i]);
}
else
{
if ( infixNotation[i].equals("*") || infixNotation[i].equals("/") )
{
if ( stk.peek().equals("+") || stk.peek().equals("-") )
{
stk.push(infixNotation[i]);
}
else if ( stk.peek().equals("*") || stk.peek().equals("/") )
{
postfixNotation = postfixNotation + stk.peek();
stk.pop();
stk.push(infixNotation[i]);
}
}
else if ( infixNotation[i].equals("+") || infixNotation[i].equals("-") )
{
if ( stk.peek().equals("+") || stk.peek().equals("-"))
// Equal level's operators can't enter the stack twice sequentially,
// so they need to be considered only once.
{
postfixNotation = postfixNotation + stk.peek();
stk.pop();
stk.push(infixNotation[i]);
}
else if ( stk.peek().equals("*") || stk.peek().equals("/") )
{
postfixNotation = postfixNotation + stack.peek();
stk.pop();
if ( stk.peek().equals("+") || stk.peek().equals("-") ) // ex + * -
{
postfixNotation = postfixNotation + stk.peek();
stk.pop();
}
stk.push(infixNotation[i]);
}
}
}
}
}
}
if (i == infixNotation.length-1) // All elements is pop()ed, when 'i' have last value
{
while(!stk.isEmpty())
{
if(stk.peek().equals("("))
{
stk.pop();
}
else if (stk.peek().equals(")"))
{
stk.pop();
}
else
{
postfixNotation = postfixNotation + stk.peek();
stk.pop();
}
}
}
}
System.out.println(postfixNotation);
return postfixNotation;
}
public void whenRightPush()
// This method will work when ')' is push()ed // I can't find proper name for this method
{
stk.pop();
while(true)
{
if ( stk.peek().equals("(") )
{
stk.pop();
break;
}
else // pop()
{
postfixNotation = postfixNotation + stk.peek();
stk.pop();
}
}
}
public void postfixCalculate(String postNotation) // Calculate the postfix notation
{
int operatorCount = 0;
int resultTemp = 0;
String[] arrayPostfixNotation = postNotation.split("", 0);
for (String str : arrayPostfixNotation)
{
aListPostfixNotation.add(str);
}
for (String str : aListPostfixNotation)
{
if (str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/"))
{
operatorCount++;
}
}
while(operatorCount > 0) {
for(int i = 0; i < aListPostfixNotation> {
if (aListPostfixNotation.get(i).equals("+") ||
aListPostfixNotation.get(i).equals("-") ||
aListPostfixNotation.get(i).equals("*") ||
aListPostfixNotation.get(i).equals("/"))
{
if(aListPostfixNotation.get(i).equals("+"))
{
resultTemp = Integer.parseInt(aListPostfixNotation.get(i-2))
+ Integer.parseInt(aListPostfixNotation.get(i-1));
}
else if(aListPostfixNotation.get(i).equals("-"))
{
resultTemp = Integer.parseInt(aListPostfixNotation.get(i-2))
- Integer.parseInt(aListPostfixNotation.get(i-1));
}
else if(aListPostfixNotation.get(i).equals("*"))
{
resultTemp = Integer.parseInt(aListPostfixNotation.get(i-2))
* Integer.parseInt(aListPostfixNotation.get(i-1));
}
else
{
resultTemp = Integer.parseInt(aListPostfixNotation.get(i-2))
/ Integer.parseInt(aListPostfixNotation.get(i-1));
}
aListPostfixNotation.remove(i-2); // Remove the used operator and operand
aListPostfixNotation.remove(i-2);
aListPostfixNotation.remove(i-2);
aListPostfixNotation.add(i-2, Integer.toString(resultTemp)); // Add the result of operation into the arraylist
operatorCount--;
break;
}
}
}
System.out.println(resultTemp);
}
}
Stack
The class contains a Scanner for no apparent reason. While it is your implementation, which does not implement the interface from the JDK, you should be aware that in the "standard" contract for Stack, (in Java as in other programming languages) the pop() method returns the removed item. (making peeking sometimes redundant)
any reason why your Stack isn't generic? It's good practice...
Java Postfix Calculator
This class violates the single responsibility principle. Besides doing what it is supposed to do (all the arithmetic calculation), It also receives input from the user, parses it and outputs the result. so your calculator cannot be used in a web app or mobile device because it can only receive input and emit output from/to the console. Your calculator should receive and return a String (or possibly return an int or float) and let the caller worry about how to get the input and where to display the output.
The constructor - it does everything. In fact, while there are other public methods, the constructor is the only interface that is used by whoever uses this Calculator, as can be seen by Main. This design poses three problems: 1) it's counter-intuitive. 2) there is no way to reuse the same instance to do multiple calculations and 3) yet another violation of the single responsibility principle. a constructor should only set up the state (instance variables) of the instance. any operation or action should be done by different methods. avoid literals. the parenthesis and operators should be defined once. either as public static final constants or better yet, as enum. putting them in an enum has the advantage that you can assign "properties" to the values, like precedence.