자바 플레이그라운드 미션1-1 문자열 계산기(beforeFeedback)

이호석·2022년 5월 15일
1

넥스트 스텝의 자바 플레이그라운드 with TDD, 클린코드 강의를 신청하여 미션 1의 1단계인 '문자열 계산기'를 만들어 보았다.

요구사항

  • 사용자가 입력한 문자열 값에 따라 사칙연산을 수행할 수 있는 계산기를 구현해야 한다.
  • 문자열 계산기는 사칙연산의 계산 우선순위가 아닌 입력 값에 따라 계산 순서가 결정된다. 즉, 수학에서는 곱셈, 나눗셈이 덧셈, 뺄셈 보다 먼저 계산해야 하지만 이를 무시한다.
  • 예를 들어 "2 + 3 * 4 / 2"와 같은 문자열을 입력할 경우 2 + 3 * 4 / 2 실행 결과인 10을 출력해야 한다.

힌트

문자열을 입력 받은 후(scanner의 nextLine() 메소드 활용) 빈 공백 문자열을 기준으로 문자들을 분리해야 한다.

String value = scanner.nextLine();
String[] values = value.split(" ");

문자열을 숫자로 변경하는 방법

int number = Integer.parseInt("문자열");

지켜야 할 규칙

  • 한 메서드에 오직 한 단계의 들여쓰기만 한다.
  • else 예약어를 쓰지 않는다.

Calculator.java

import java.util.NoSuchElementException;
import java.util.Scanner;

public class Calculator {

    public int execute() {
        Scanner scanner = new Scanner(System.in);
        String value;
        try {
             value = scanner.nextLine();
        }catch (NoSuchElementException e){
            System.out.println("공백은 입력할 수 없습니다.");
            return 0;
        }

        String[] values = value.split(" ");

        int result = 0;
        try {
            result = inputStringArray(values);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("띄워쓰기가 잘못되었습니다.");
        } catch (NumberFormatException e) {
            System.out.println("숫자 자리에 다른 문자를 입력했거나 띄워쓰기가 잘못되었습니다.");
        }

        scanner.close();
        return result;
    }

    public int inputStringArray(String[] values) {
        int result = Integer.parseInt(values[0]);
        for (int i = 1; i < values.length; i += 2) {
            result = calculate(result, values[i], Integer.parseInt(values[i + 1]));
        }
        return result;
    }

    public int calculate(int first, String operator, int second) {
        switch (operator) {
            case "+":
                return add(first, second);
            case "-":
                return subtract(first, second);
            case "*":
                return multiply(first, second);
            case "/":
                return divide(first, second);
        }
        throw new IllegalArgumentException("연산자 자리에 확인되지 않은 문자가 들어왔습니다. 연산자 : " + operator);
    }

    int add(int first, int second) {
        return first + second;
    }

    int subtract(int first, int second) {
        return first - second;
    }

    int multiply(int first, int second) {
        return first * second;
    }

    int divide(int first, int second) {
        try {
            return first / second;
        } catch (ArithmeticException e) {
            System.out.println("0으로 나누는 것은 불가능 합니다");
        }
        return 0;
    }

}

CalculatorTest.java

import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

public class CalculatorTest {

    Calculator calculator = new Calculator();

    public static void inputHandling(String userInput) {
        InputStream in = new ByteArrayInputStream(userInput.getBytes());
        System.setIn(in);
    }

    @Test
    void complexExecute() {
        inputHandling("2 + 3 - 0 * 4 / 2");
        assertThat(calculator.execute()).isEqualTo(10);
    }

    @Test
    void add() {
        inputHandling("2 + 3 + 4 + 5");
        assertThat(calculator.execute()).isEqualTo(14);
    }

    @Test
    void subtract() {
        inputHandling("10 - 2 - 3 - 6");
        assertThat(calculator.execute()).isEqualTo(-1);
    }

    @Test
    void multiply() {
        inputHandling("2 * 3 * 4 * 5");
        assertThat(calculator.execute()).isEqualTo(120);
    }

    @Test
    void divide() {
        inputHandling("10 / 2 / 5");
        assertThat(calculator.execute()).isEqualTo(1);
    }

    @Test
    void exceptionTest() {
        inputHandling("1 C 3 * 4 / 2");
        assertThatThrownBy(() -> calculator.execute()).isInstanceOf(IllegalArgumentException.class).hasMessageContaining("연산자");

        inputHandling("");
        assertThat(calculator.execute()).isEqualTo(0);
    }
}

이 과정은 개인 피드백은 없고 공통피드백만 존재한다고 한다. 강의의 가격이 저렴하다보니 그건 당연하다고 생각하는데, 미션1에서는 문자열 계산기는 없고 숫자야구게임만 피드백이 존재하는 것 같다. 하는 수 없이 구글링을 통해 다른 강의에서 진행된 다른 분의 개인 피드백을 살펴봤다.

다음 포스트에서는 리팩토링된 코드를 올릴 예정이다.

0개의 댓글