HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Basic Postfix Calculator in Java

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
javapostfixcalculatorbasic

Problem

I recently posted some sample code that I was providing students with and got great feedback so figured I post another one of the examples I will be providing students with. (See Simple Example of an Iterable and an Iterator in Java)

This one is a simple postfix calculator. The main learning objectives are basic inheritance, trees, post-order and in-order traversals and stack based parsing of postfix expressions.

First, the CLI code:

import java.util.Scanner;

public class PostfixCLI {
    public static void main(String[] args) {
        System.out.println("Enter postfix expression to evaluate, 'exit' to exit.");
        Scanner in = new Scanner(System.in);
        while (true) {
            try {
                System.out.print(">>> ");
                String input = in.nextLine();

                if (input.equals("exit")) {
                    break;
                }

                Expression expression = Expression.parsePostOrder(input);
                System.out.format("%s = %.4f\n",
                                  expression.toString(),
                                  expression.evaluate());
            } catch (InvalidExpressionException e) {
                System.out.println("Invalid expression: " + e.getMessage());
                continue;
            } catch (RuntimeException e) {
                System.out.println("Runtime error: " + e.getMessage());
                continue;
            } catch (Exception e) {
                System.out.println("Unknown error: " + e.getMessage());
                continue;
            }
        }
    }
}


And the Expression.java file that does most of the work.

```
import java.util.Stack;
import java.util.Scanner;

public abstract class Expression {
public abstract double evaluate();

public String toPostOrder() {
return this.toString();
}

public String toInOrder() {
return this.toString();
}

/*
* Parse an expresssion tree given a string and return

Solution

This answer will focus on the main method

Separation of concerns:

You have the full story in your main method. You do: Exception-Handling, printing, prompting and a little bit of parsing:

You might want to move that to different methods. The abstraction level in main method should be so high, it reads more like plain english instead of code:

public static void main(String[] args){
    while(true){
        try{
           String input = promptUserForInput();
           if(isExitCode(input)){
               break;
           }
           parseExpressionAndPrintResults(input);
        }
        catch(Exception e){
            System.out.println("Unknown error: " + e.getMessage());
            continue;
        }
    }
}


Error Handling:

Your catch of RuntimeException is redundant. Runtime Exceptions will also be caught when catching Exception. That is one of the reasons, why it is considered bad practice to catch Exception.

Accordingly you can remove:

catch(RuntimeException e){
    System.out.println("Runtime Error: " + e);
    continue;
}


Prompting the user for input:

I had an answer on a different post, which mostly concerned itself with that, you might want to have a look at it for more on parsing numbers.

Other than that:

System.out.println("Enter postfix expression to evaluate, 'exit' to exit.");


It is generally considered easier to use named constants instead of long strings, how does this look to you:

System.out.println(PROMPT);


And while we're at it, the prompt you issue will be "shoved" out of the screen. I prefer prompting the user before every input. That's why I would write the aforementioned promtUserForInput() as follows:

private String promptUserForInput(){
    final String PROMPT = "Enter postfix expression to evaluate, 'exit' to exit.\n >>> ";
    System.out.println(PROMPT);
    Scanner in = new Scanner(System.in); // you can move that to class-level if you
                                         //want to minimize the overhead from creating it.
    return in.nextLine();
}


Parsing the input:

Well the rest is simple, I'd just move the code that you didn't see yet into the parseExpressionAndPrintResults method.

Code Snippets

public static void main(String[] args){
    while(true){
        try{
           String input = promptUserForInput();
           if(isExitCode(input)){
               break;
           }
           parseExpressionAndPrintResults(input);
        }
        catch(Exception e){
            System.out.println("Unknown error: " + e.getMessage());
            continue;
        }
    }
}
catch(RuntimeException e){
    System.out.println("Runtime Error: " + e);
    continue;
}
System.out.println("Enter postfix expression to evaluate, 'exit' to exit.");
System.out.println(PROMPT);
private String promptUserForInput(){
    final String PROMPT = "Enter postfix expression to evaluate, 'exit' to exit.\n >>> ";
    System.out.println(PROMPT);
    Scanner in = new Scanner(System.in); // you can move that to class-level if you
                                         //want to minimize the overhead from creating it.
    return in.nextLine();
}

Context

StackExchange Code Review Q#49027, answer score: 8

Revisions (0)

No revisions yet.