diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..bcf30bf --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'java-calculator' + diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..0680f67 --- /dev/null +++ b/src/README.md @@ -0,0 +1,61 @@ +# Java-Calculator + +Create a string calculator and write test code for it + +## Contributor +- oereo + +## Branch structure + +### oereo branch +* from `oereo/java-calculator[oereo branch]` to `biforest/java-calculator [oereo branch]` + +### java-calculator-structure branch +* Feature branch : Branch to develop the function ex)feature/java-calculator +* Fix branch : Branch to fix the function ex)fix/java-calculator + +## TDD +### Failure case +#### (1) When divided by 0 +```console + 연산을 입력해주세요 : 2/0 // error +``` +#### (2) When two or more operation symbols appear in a row +```console + 연산을 입력해주세요 : 2++0 // error +``` +#### (3) When the operation symbol appears at the beginning +```console + 연산을 입력해주세요 : +2+0 // error +``` +#### (4) When special characters other than operation symbols are entered +```console + 연산을 입력해주세요 : 2^4 // error +``` +#### (5) When characters excluding numbers and operators are entered +```console + 연산을 입력해주세요 : 2ㄱㄴ4*4 // error +``` +#### (6) When the formula ends with an operation symbol +```console + 연산을 입력해주세요 : 2-1* // error +``` +## Structure +#### 1. Class +- Calculator class + - `+ class` + - `- class` + - `* class` + - `/ class` +- Input class +- Output class + - `Error message` output + - `Calculation result` output +- Error exception class + - Precautions : only use `try ~ catch` +- Init class + - When an error occurs, reset after outputting an error message + - Reset and input when pressing any key value + +#### 2. Algorithm +- DFS, Node \ No newline at end of file diff --git a/src/main/java/calculator/AddOperation.java b/src/main/java/calculator/AddOperation.java new file mode 100644 index 0000000..1b0f64c --- /dev/null +++ b/src/main/java/calculator/AddOperation.java @@ -0,0 +1,19 @@ +package calculator; + +public class AddOperation implements OperationInterface { + @Override + public int operationPriority() { + return 1; + } + + @Override + public String operationName() { + return "+"; + } + + @Override + public int calculation(int beforeNumber, int afterNumber) { + int Result = beforeNumber + afterNumber; + return Result; + } +} diff --git a/src/main/java/calculator/Application.java b/src/main/java/calculator/Application.java new file mode 100644 index 0000000..62e6657 --- /dev/null +++ b/src/main/java/calculator/Application.java @@ -0,0 +1,11 @@ +package calculator; + + +public class Application { + public static void main(String[] args) { + + // Declare calculator object and start calculation + Calculator calculator = new Calculator(); + calculator.calculation(); + } +} diff --git a/src/main/java/calculator/ArithmeticExpressionStack.java b/src/main/java/calculator/ArithmeticExpressionStack.java new file mode 100644 index 0000000..1762174 --- /dev/null +++ b/src/main/java/calculator/ArithmeticExpressionStack.java @@ -0,0 +1,46 @@ +package calculator; + + +interface Stack{ + boolean isEmpty(); + String pop(); + void clear(); +} + +public class ArithmeticExpressionStack implements Stack { + private int stackSize; + private int flag; + private String stack[]; + + public ArithmeticExpressionStack(String[] equation, int stackSize){ + clear(); + flag = 0; + this.stackSize = stackSize; + stack = equation; + } + + public String pop(){ + if(isEmpty()){ + return "스택이 존재하지 않습니다."; + } + else{ + return stack[flag++]; + } + } + + public boolean isEmpty(){ + return (flag == this.stackSize); + } + + public void clear(){ + if(!isEmpty()){ + flag = -1; + this.stackSize = stackSize; + } + } + + public int getStackSize(){ + return this.stackSize; + } + +} diff --git a/src/main/java/calculator/Calculator.java b/src/main/java/calculator/Calculator.java new file mode 100644 index 0000000..10e701e --- /dev/null +++ b/src/main/java/calculator/Calculator.java @@ -0,0 +1,132 @@ +package calculator; + +import java.util.Scanner; + + +public class Calculator { + Message message = new Message(); + + /** + * calculation method + * 1. getEquation - Receives numeric expression in string format entered by user + * 2. Put numeric expressions on the stack + * 3. Passing the stack to the operatorSetting method + * + * return type : void + */ + public void calculation(){ + String[] equation_list = getEquation(); + ArithmeticExpressionStack arithmeticExpressionStack = new ArithmeticExpressionStack(equation_list, equation_list.length); + OperatorSetting(arithmeticExpressionStack); + + } + + /** + * OperatorSetting method + * 1. Pop each operator and number onto the stack. + * 2. Perform error exception check and calculate + * 3. After the calculation process is complete, call init() to determine whether to return the calculator + * + * return type : void + */ + public void OperatorSetting(ArithmeticExpressionStack arithmeticExpressionStack) { + ErrorException exceptionCheck = new ErrorException(); + String firstString = arithmeticExpressionStack.pop(); + + // Error checking when converting string to int + int cumulativeResult = exceptionCheck.NumericalError(firstString); + + for(int i = 0; i<(arithmeticExpressionStack.getStackSize())/2;i++){ + String operator = arithmeticExpressionStack.pop(); + String secondString = arithmeticExpressionStack.pop(); + int secondNumber = exceptionCheck.NumericalError(secondString); + + // calculated value are continuously accumulated + cumulativeResult = chooseOperatorAndCalculate(cumulativeResult, operator, secondNumber); + } + + if(cumulativeResult != 0){ + message.calculationResult(cumulativeResult); + } + + // Whether to re-execute after calculation + init(); + } + + /** + * chooseOperatorAndCalculate method + * 1. Pop each operator and number onto the stack. + * 2. Perform error exception check and calculate + * 3. After the calculation process is complete, call init() to determine whether to return the calculator + * + * return type : int + */ + public int chooseOperatorAndCalculate(int firstNumber, String operator, int SecondNumber){ + AddOperation addOperation = new AddOperation(); + SubOperation subOperation = new SubOperation(); + MultiplyOperation multiplyOperation = new MultiplyOperation(); + DivideOperation divideOperation = new DivideOperation(); + int result = 0; + + // When the operator is equal to "+" + if (operator.equals(addOperation.operationName())){ + result = addOperation.calculation(firstNumber, SecondNumber); + } + + // When the operator is equal to "-" + else if (operator.equals(subOperation.operationName())){ + result = subOperation.calculation(firstNumber, SecondNumber); + } + + // When the operator is equal to "*" + else if (operator.equals(multiplyOperation.operationName())){ + result = multiplyOperation.calculation(firstNumber, SecondNumber); + } + + // When the operator is equal to "/" + else if (operator.equals(divideOperation.operationName())){ + result = divideOperation.calculation(firstNumber, SecondNumber); + } + + // Raise error when a symbol that does not correspond to the arithmetic operations(+, -, *, /) comes + else{ + message.exceptionResult("NOT_OPERATOR"); + } + + return result; + } + + /** + * init method + * - Input "1" to redo calculator. + * - Input another key to exit + * + * return type : void + */ + public void init(){ + Scanner scanner = new Scanner(System.in); + System.out.println("계산을 계속 진행하시려면 1, 멈추시려면 임의의 다른키를 눌러주세요"); + String value = scanner.nextLine(); + + if(value.equals("1")){ + calculation(); + } + else{ + System.exit(0); + } + } + + /** + * getEquation method + * - Method to receive user input data + * + * return type : void + */ + public String[] getEquation(){ + Scanner scanner = new Scanner(System.in); + System.out.print("수식을 입력해주세요 : "); + String value = scanner.nextLine(); + String[] values = value.split(" "); + return values; + } +} diff --git a/src/main/java/calculator/DivideOperation.java b/src/main/java/calculator/DivideOperation.java new file mode 100644 index 0000000..1efd04d --- /dev/null +++ b/src/main/java/calculator/DivideOperation.java @@ -0,0 +1,26 @@ +package calculator; + +public class DivideOperation implements OperationInterface { + @Override + public int operationPriority() { + return 1; + } + + @Override + public String operationName() { + return "/"; + } + + @Override + public int calculation(int beforeNumber, int afterNumber) { + Message message = new Message(); + try{ + int Result = beforeNumber / afterNumber; + return Result; + } + catch (ArithmeticException e){ + message.exceptionResult("INVALID_DIVIDE"); + } + return 0; + } +} diff --git a/src/main/java/calculator/ErrorException.java b/src/main/java/calculator/ErrorException.java new file mode 100644 index 0000000..33f64b8 --- /dev/null +++ b/src/main/java/calculator/ErrorException.java @@ -0,0 +1,25 @@ +package calculator; + +import java.util.InputMismatchException; + +public class ErrorException { + Message message = new Message(); + + /** + * NumericalError method + * - Raise error when string is not converted to int + * + * return type : void + */ + public int NumericalError(String number) { + int numberConverted = 0; + try { + numberConverted = Integer.parseInt(number); + } catch (NumberFormatException e) { + message.exceptionResult("INVALID_EQUATION"); + Calculator calculator = new Calculator(); + calculator.init(); + } + return numberConverted; + } +} diff --git a/src/main/java/calculator/Message.java b/src/main/java/calculator/Message.java new file mode 100644 index 0000000..fc6db1f --- /dev/null +++ b/src/main/java/calculator/Message.java @@ -0,0 +1,32 @@ +package calculator; + +import java.util.HashMap; + +/** + * Message class + * - message output class + * + * return type : void + */ +public class Message { + HashMap exceptionMessageList = new HashMap(); + + // Result output method when operation is normally performed + public void calculationResult(int result){ + System.out.print("결과 : "); + System.out.println(result); + } + + // Error message list management method + private void exceptionMessageList(){ + exceptionMessageList.put("NOT_OPERATOR", "사칙연산 기호에 해당하지 않는 기호가 존재합니다."); + exceptionMessageList.put("INVALID_EQUATION", "잘못된 연산식입니다."); + exceptionMessageList.put("INVALID_DIVIDE", "0으로 나눌수가 없습니다."); + } + + // Error message output method + public void exceptionResult(String exceptionKeyword){ + exceptionMessageList(); + System.out.println(exceptionMessageList.get(exceptionKeyword)); + } +} diff --git a/src/main/java/calculator/MultiplyOperation.java b/src/main/java/calculator/MultiplyOperation.java new file mode 100644 index 0000000..f03451a --- /dev/null +++ b/src/main/java/calculator/MultiplyOperation.java @@ -0,0 +1,19 @@ +package calculator; + +public class MultiplyOperation implements OperationInterface { + @Override + public int operationPriority() { + return 1; + } + + @Override + public String operationName() { + return "*"; + } + + @Override + public int calculation(int beforeNumber, int afterNumber) { + int Result = beforeNumber * afterNumber; + return Result; + } +} diff --git a/src/main/java/calculator/Operation.java b/src/main/java/calculator/Operation.java new file mode 100644 index 0000000..d47ad26 --- /dev/null +++ b/src/main/java/calculator/Operation.java @@ -0,0 +1,14 @@ +package calculator; + +interface OperationInterface { + public int operationPriority(); + + public String operationName(); + + public int calculation(int beforeNumber, int afterNumber); +} + + + + + diff --git a/src/main/java/calculator/SubOperation.java b/src/main/java/calculator/SubOperation.java new file mode 100644 index 0000000..a0adeec --- /dev/null +++ b/src/main/java/calculator/SubOperation.java @@ -0,0 +1,19 @@ +package calculator; + +public class SubOperation implements OperationInterface { + @Override + public int operationPriority() { + return 1; + } + + @Override + public String operationName() { + return "-"; + } + + @Override + public int calculation(int beforeNumber, int afterNumber) { + int Result = beforeNumber - afterNumber; + return Result; + } +} \ No newline at end of file diff --git a/src/main/java/empty.txt b/src/main/java/empty.txt deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/java/calculator/CalculatorTest.java b/src/test/java/calculator/CalculatorTest.java new file mode 100644 index 0000000..943ea75 --- /dev/null +++ b/src/test/java/calculator/CalculatorTest.java @@ -0,0 +1,83 @@ +package calculator; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; + +import static org.junit.jupiter.api.Assertions.*; + +class CalculatorTest { + + @BeforeEach + void setUp() { + Calculator calculator = new Calculator(); + } + + @Test + void calculation() { + } + + @Test + void operatorSetting() { + } + + @Test + void addChooseOperatorAndCalculate(){ + Calculator calculator = new Calculator(); + int firstNumber = 2; + String operator = "+"; + int secondNumber = 3; + int result = 0; + result = calculator.chooseOperatorAndCalculate(firstNumber, operator, secondNumber); + assertEquals(5, result); + } + + @Test + void subChooseOperatorAndCalculate(){ + Calculator calculator = new Calculator(); + int firstNumber = 2; + String operator = "-"; + int secondNumber = 3; + int result = 0; + result = calculator.chooseOperatorAndCalculate(firstNumber, operator, secondNumber); + assertEquals(-1, result); + } + + @Test + void multiplyChooseOperatorAndCalculate(){ + Calculator calculator = new Calculator(); + int firstNumber = 2; + String operator = "*"; + int secondNumber = 3; + int result = 0; + result = calculator.chooseOperatorAndCalculate(firstNumber, operator, secondNumber); + assertEquals(6, result); + } + + @Test + void divideChooseOperatorAndCalculate(){ + Calculator calculator = new Calculator(); + int firstNumber = 9; + String operator = "/"; + int secondNumber = 3; + int result = 0; + result = calculator.chooseOperatorAndCalculate(firstNumber, operator, secondNumber); + assertEquals(3, result); + } + + @Test + void invalidCalculation(){ + // todo refactoring + assertThrows(NumberFormatException.class, new Executable() { + @Override + public void execute() throws Throwable { + Calculator calculator = new Calculator(); + + String[] equation_list = {"+", "1", "+"}; + ArithmeticExpressionStack arithmeticExpressionStack = new ArithmeticExpressionStack(equation_list, equation_list.length); + + calculator.OperatorSetting(arithmeticExpressionStack); + } + }); + } +} \ No newline at end of file