-
Notifications
You must be signed in to change notification settings - Fork 48
Calculator
Hu JiaJun edited this page Nov 29, 2020
·
1 revision
/**
* Class Input reads a line from the system console (System.in).
* It displays a numbered prompt.
*/
import java.util.Scanner;
public class Input {
// Static members and methods
private static int lineNo = 0;
static Scanner sc = new Scanner(System.in).useDelimiter("\\n");
public static Input readInput() {
return new Input();
}
// Instance members and methods
private final String line;
private Input() {
lineNo++;
System.out.printf("[%d]=> ", lineNo);
this.line = sc.next();
}
public String getLine() {
return this.line;
}
public int getLineNum() {
return this.lineNo;
}
}
/**
* This class serves only to store the result of the calculation
* in the form of a message string. A display method is provided
* to print the message to console (System.out).
*/
public class Result {
private final String message;
public Result(String m) {
this.message = m;
}
public void display() {
System.out.println(message);
}
}
/**
* Class Statement is the workhorse of the calculator.
* It initializes the hashtable to store the command and its associated
* lambda function. To run the command, its name is used to lookup the table
* to retrieve the lambda, which is then applied to the arguments.
*
* There is a lot of code to handle errors, which are due to:
* (a) unknown command, (b) wrong type of arguments, (c) too many or too few
* arguments. Such code clutters the main code and obscures the key idea.
* There is room for improvement!
*/
import java.util.Scanner;
import java.util.function.Function;
import java.util.NoSuchElementException;
import java.util.InputMismatchException;
import java.util.Hashtable;
public class Statement {
// static members and methods
// This stores the function for each command
private static Hashtable < String, Function < Double[], Double >> commandTable;
// This stores the number of arguments for each command
private static Hashtable < String, Integer > argsTable;
public static Statement parse(Input input) {
return new Statement(input.getLine());
}
/**
* Error input, return 0.0
* Accept a double array with 0 elements = 0 argument
*/
private static final Function < Double[], Double >
error = x - > 0.0;
/**
* Addition
* Accept a double array with 2 elements = 2 arguments
* Example: add 1 2
*/
private static final Function < Double[], Double >
addition = x - > x[0] + x[1];
/**
* Multiplication
* Accept a double array with 2 elements = 2 arguments
* Example: mult 3 4
*/
private static final Function < Double[], Double >
multiplication = x - > x[0] * x[1];
/**
* Reciprocal
* Accept a double array with 1 element = 1 argument
* Example: recip 5
*/
private static final Function < Double[], Double >
reciprocal = x - > 1.0 / x[0];
/**
* Percentage after Multiplication
* Accept a double array with 2 elements = 2 arguments
* Example: % 6 7
*/
private static final Function < Double[], Double >
percentage = x - > x[0] * x[1] / 100.0;
// Initialization
public static void initialize() {
commandTable = new Hashtable < > ();
argsTable = new Hashtable < > ();
/**
* Error input, return 0.0
* Accept a double array with 0 elements = 0 argument
*/
commandTable.put("err", error);
argsTable.put("err", 0);
/**
* Addition
* Accept a double array with 2 elements = 2 arguments
*/
commandTable.put("add", addition);
argsTable.put("add", 2);
/**
* Multiplication
* Accept a double array with 2 elements = 2 arguments
*/
commandTable.put("mult", multiplication);
argsTable.put("mult", 2);
/**
* Reciprocal
* Accept a double array with 1 element = 1 argument
*/
commandTable.put("recip", reciprocal);
argsTable.put("recip", 1);
/**
* Percentage after Multiplication
* Accept a double array with 2 elements = 2 arguments
*/
commandTable.put("%", percentage);
argsTable.put("%", 2);
}
// Instance member and methods
private String command;
private Double[] arguments;
private String message;
// Input Method
public Statement(String input) {
/**
* Input format: <command> <arg1> [<arg2>]
*
* Example:
* add 1 2
* mult 3 4
* recip 5
* % 6 7
*/
Scanner sc = new Scanner(input);
// Parse command
String c = sc.next();
// If the command is not err, add, mult, recip or %
if (!commandTable.containsKey(c)) {
this.command = "err";
this.message = String.format("Bad command! %s", c);
return;
}
this.command = c;
// Parse arguments
int numberArgs = argsTable.get(this.command);
this.arguments = new Double[numberArgs];
try {
for (int i = 0; i < numberArgs; i++) {
this.arguments[i] = sc.nextDouble();
}
if (sc.hasNext()) {
this.command = "err";
this.message = "Too many arguments!";
}
} catch (InputMismatchException e) {
this.command = "err";
this.message = "Bad arguments!";
} catch (NoSuchElementException e) {
this.command = "err";
this.message = "Too few arguments!";
}
}
public Result evaluate() {
if (!this.command.equals("err")) {
// commandTable.get(this.command): Function object
// this.arguments: Double[] object
double r = commandTable.get(this.command).apply(this.arguments);
this.message = String.format("%f", r);
}
return new Result(this.message);
}
}
/**
* Calc.java implements a simple, command-line calculator.
* User enters command in the form: <command> <arg1> <arg2>
* Example: add 3 5
* Currently, only 4 command are implemented: add, mult, recip, %,
* denoting addition, multiplcation, reciprocal, and percentage, respectively.
* To compile, put all the files in the same directory:
* Calc.java, Input.java, Statement.java, Results.java
* Then type:
* javac *.java
* java Calc
*/
import java.util.NoSuchElementException;
public class Calc {
public static void main(String[] args) {
// Initialize the calculator
Statement.initialize();
try {
while (true) {
Input input = Input.readInput();
Statement statement = Statement.parse(input);
Result result = statement.evaluate();
result.display();
}
} catch (NoSuchElementException e) {
// break out of while loop; end program
}
}
}
Peer Learning
Codecrunch Contributions
Piazza Contributions
Wiki Contributions
Guides
Setting Up Checkstyle
Setting Up Java
Setting Up MacVim
Setting Up Sunfire
Setting Up Unix For Mac
Setting Up Unix For Windows
Setting Up Vim
Setting up SSH Config
CS2030 Contents
Lecture 1 SummaryCompile-run vs Run-time Summary
Quick Guide To Abstraction
Generics and Variance of Types
Comparable vs Comparator
Summary of completable future
CS2030S Notes
ELI5 Optional.map vs Optional.flatMap
PECS Example Code
Java Collection Framework (Iterator)
Generic
Generic Type Parameter and Generic Wildcard
Calculator
Lambda-Expression
Single Abstract Method (SAM)
Method Reference
Functional Interfaces 2
Simple Usage of Sandbox
Associative-but-not-commutative
Higher Order function
Functional Programming
Calculator With Functor
Eager Evaluation VS Lazy Evaluation
Simple Usage of Lazy Evaluation
Lazy Evaluation for LazyList
Lazy Evaluation for BinaryTree
Stream
Parallel Stream
Optional
Simple Usage of Stream
Asynchronous Programming
Notes on CompletableFuture
Notes on CompletableFuture 2
Simple Usage of CompletableFuture
Mind Map
Exception Handling
Links
CS2030 Java Style Guide
CS2030 Javadoc Specification
JDK 11 Download Link
JDK 11 API Docs
Codecrunch
Piazza Forum