diff --git a/README.md b/README.md index e79684b..791fe72 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,18 @@ String[] values = value.split(" "); - 문자열을 숫자로 변경하는 방법 `int number = Integer.parseInt("문자열");` + +--- + +### 기능 +- 예외 + - [x] 숫자로 시작하지 않을 경우 + - [x] 띄어쓰기가 잘 안 돼서 숫자와 문자가 섞였을 경우(공백문자 미사용) + - [x] 숫자와 연산자 이외의 문자 + - [x] 연산자나 숫자가 두 번 이상 연속으로 나올 경우 +- 순서 + - [x] 문자열 입력 받기 + - [x] 띄어쓰기로 분리해서 배열에 넣기 + - [x] 예외 처리 + - [x] 피연산자(operand 숫자)와 연산자(operator +-/*)로 나누기 + - [x] 계산하기 diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 0000000..09133f0 --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,20 @@ +import java.util.List; +import java.util.Scanner; + +import calculator.Calculator; +import calculator.Operation; + +public class Application { + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + String input = scanner.nextLine(); + + Operation operation = new Operation(input); + List operands = operation.getOperands(); + List operators = operation.getOperators(); + + Calculator calculator = new Calculator(); + double result = calculator.calculate(operands, operators); + System.out.println("result = " + result); + } +} diff --git a/src/main/java/calculator/Calculator.java b/src/main/java/calculator/Calculator.java new file mode 100644 index 0000000..27c96e8 --- /dev/null +++ b/src/main/java/calculator/Calculator.java @@ -0,0 +1,42 @@ +package calculator; + +import java.util.List; + +public class Calculator { + + public double calculate(List operands, List operators) { + double result = operands.get(0); + int numOfOperations = operators.size(); + int times = 0; + + while (times < numOfOperations) { + result = fourFundamentalArithmeticOperations(result, operators.get(times), operands.get(++times)); + } + + return result; + } + + public double fourFundamentalArithmeticOperations(double tempResult, char operator, double operand) { + double result; + + switch (operator) { + case '+': + result = tempResult + operand; + break; + case '-': + result = tempResult - operand; + break; + case '*': + result = tempResult * operand; + break; + case '/': + result = tempResult / operand; + break; + default: + result = 0; + break; + } + + return result; + } +} diff --git a/src/main/java/calculator/Operation.java b/src/main/java/calculator/Operation.java new file mode 100644 index 0000000..54dd0b9 --- /dev/null +++ b/src/main/java/calculator/Operation.java @@ -0,0 +1,65 @@ +package calculator; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class Operation { + private final String[] operation; + private List operands; + private List operators; + + public Operation(String input) { + this.operation = input.split(" "); + validateOperation(); + splitOperation(); + } + + public void validateOperation() { + validateOtherSymbols(); + validateFirstIndex(); + validateDuplicate(); + } + + public void validateOtherSymbols() { + for (String tempStr : operation) { + if (!(tempStr.matches("^[0-9]*$") || tempStr.matches("^\\-[1-9]\\d*$") || tempStr.matches("[+*/-]"))) + throw new IllegalArgumentException("한 String에 숫자와 연산자가 함께 있거나, 숫자 연산자 이외의 입력입니다."); + } + } + + public void validateFirstIndex() { + if (operation[0].matches("[+*/-]")) { + throw new IllegalArgumentException("숫자로 시작해야 합니다."); + } + } + + public void validateDuplicate() { + for (int i = 0; i < operation.length - 1; i++) { + if ((!operation[i].matches("[+*/-]") && !operation[i + 1].matches("[+*/-]")) + || (operation[i].matches("[+*/-]") && operation[i + 1].matches("[+*/-]"))) { + throw new IllegalArgumentException("기호나 숫자가 두 번 연속 입력되었습니다."); + } + } + } + + public void splitOperation() { + operands = Arrays.stream(this.operation) + .filter(operand -> operand.matches("^[0-9]*$") || operand.matches("^\\-[1-9]\\d*$")) + .map(Integer::parseInt) + .collect(Collectors.toList()); + + operators = Arrays.stream(this.operation) + .filter(operator -> operator.matches("[+*/-]")) + .map(operator -> operator.charAt(0)) + .collect(Collectors.toList()); + } + + public List getOperands() { + return operands; + } + + public List getOperators() { + return operators; + } +} diff --git a/src/test/java/calculator/CalculatorTest.java b/src/test/java/calculator/CalculatorTest.java new file mode 100644 index 0000000..be845ed --- /dev/null +++ b/src/test/java/calculator/CalculatorTest.java @@ -0,0 +1,44 @@ +package calculator; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; + +class CalculatorTest { + + private List operands = Arrays.asList(2, 4, 3, 7, 5); + private List operators = Arrays.asList('+', '-', '*', '/'); + + private Calculator calculator = new Calculator(); + + @Test + void calculate() { + double result; + + result = calculator.calculate(operands, operators); + + assertThat(result).isEqualTo(4.2); + } + + @Test + void 사칙연산() { + double addition, subtraction, multiplication, division, wrongOperatorResult; + + addition = calculator.fourFundamentalArithmeticOperations(operands.get(0), operators.get(0), operands.get(1)); + subtraction = calculator.fourFundamentalArithmeticOperations(operands.get(0), operators.get(1), + operands.get(1)); + multiplication = calculator.fourFundamentalArithmeticOperations(operands.get(0), operators.get(2), + operands.get(1)); + division = calculator.fourFundamentalArithmeticOperations(operands.get(0), operators.get(3), operands.get(1)); + wrongOperatorResult = calculator.fourFundamentalArithmeticOperations(operands.get(0), '?', operands.get(1)); + + assertThat(addition).isEqualTo(6.0); + assertThat(subtraction).isEqualTo(-2.0); + assertThat(multiplication).isEqualTo(8.0); + assertThat(division).isEqualTo(0.5); + assertThat(wrongOperatorResult).isEqualTo(0); + } +} diff --git a/src/test/java/calculator/OperationTest.java b/src/test/java/calculator/OperationTest.java new file mode 100644 index 0000000..ac7a14c --- /dev/null +++ b/src/test/java/calculator/OperationTest.java @@ -0,0 +1,64 @@ +package calculator; + +import static org.assertj.core.api.Assertions.*; + +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class OperationTest { + + private Operation operation; + + @BeforeEach + void setUp() { + operation = null; + } + + @Test + void validateMixed() { + String wrongInput = "2/ 3"; + + assertThatThrownBy(() -> operation = new Operation(wrongInput)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("한 String에 숫자와 연산자가 함께 있거나, "); + } + + @Test + void validateOtherSymbols() { + String wrongInput = "( 3 - 4"; + + assertThatThrownBy(() -> operation = new Operation(wrongInput)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("숫자 연산자 이외의 입력입니다"); + } + + @Test + void validateFirstIndex() { + String wrongInput = "- 2 + 1"; + + assertThatThrownBy(() -> operation = new Operation(wrongInput)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("숫자로 시작해야 합니다."); + } + + @Test + void validateDuplicate() { + String wrongInput = "2 * / 1 + 3"; + + assertThatThrownBy(() -> operation = new Operation(wrongInput)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("기호나 숫자가 두 번 연속"); + } + + @Test + void splitOperation() { + String input = "2 + -3 * 4 / 2"; + + operation = new Operation(input); + + assertThat(operation.getOperands()).isEqualTo(Arrays.asList(2, -3, 4, 2)); + assertThat(operation.getOperators()).isEqualTo(Arrays.asList('+', '*', '/')); + } +}