내일배움캠프/TIL

[Spring_4기 본캠프] 3주차 - 계산기 lv2와 트러블 슈팅 | Day 24

austindynasty 2024. 11. 19. 22:11

1. 가짜코드와 진짜코드

계산기 lv3 을 구현하기 전에, 내가 lv1과 lv2 를 완벽하게 이해하고 모든 코드를 손으로 직접 작정할 수 있는 지가 먼저 확인되어야 했다.

아무래도 구글검색이나 챗GPT에 물어보면서 이것저것 코드를 짜깁기 한 것이라서 사실 내 손으로 손수 작성한 '진짜'코드라고 보긴 어려웠다. 그래서 작성해놨던 모든 코드를 지우고 처음부터 다시 시작하기로 했다. 과제 제출 하루 전에 하기에는 위험했지만.. 위기를 알면서도 

그냥 있으면 그게 진짜 위기다 라는 어록이 떠오르며.. 불도저처럼 모든 코드를 밀어버렸다.

 

2. 진짜 코드를 작성하라 

 

package lv2;

import java.util.Scanner;

public class CalculatorApp {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Calculator calculator = new Calculator();

        while (true) {
            System.out.print("계산을 진행하시겠습니까? (Yes or No) : ");
            String input = sc.next();

            if (input.equalsIgnoreCase("no")) {
                break;
            } else if (!input.equalsIgnoreCase("yes")) {
                System.out.print("Yes 또는 No만 입력할 수 있습니다.");
                continue;
            }

            System.out.print("첫 번째 숫자를 입력하세요 : ");
            int num1 = sc.nextInt();

            System.out.print("연산자를 입력하세요 ( +, -, *, /) : ");
            String operator = sc.next();

            System.out.print("두 번째 숫자를 입력하세요 : ");
            int num2 = sc.nextInt();

            int result = calculator.calculate(num1, num2, operator);
            System.out.println("계산 결과 : " + num1 + operator + num2 + " = " + result);
            System.out.println("계산 기록 : " + calculator.getHistory());
        }
    }
}
package lv2;

import java.util.LinkedList;

public class Calculator {
    private final LinkedList<Integer> linkedList = new LinkedList<>();

    public int calculate(int num1, int num2, String operator) {
        int result = 0;

        switch (operator) {
            case "+" -> result = num1 + num2;
            case "-" -> result = num1 - num2;
            case "*" -> result = num1 * num2;
            case "/" -> {
                if (num1 ==0) {
                    System.out.println("0으로 나눌 수 없습니다. 다시 입력하세요.");
                }
                result = num1 / num2;
            }
            default -> System.out.println("잘못된 연산자 입니다. ( +, -, *, /) 만 입력할 수 있습니다.");
        }
        addResult(result);
        return result;
    }
    public LinkedList<Integer> getHistory() {
        return new LinkedList<>(linkedList);
    }
    private void addResult(int result) {
        if (linkedList.size() >= 5) {
            linkedList.pollFirst();
        }
        linkedList.add(result);
    }
}

 

예외처리를 위해선 예외를 예상할 수 있어야 한다. 혹시나해서 연산자에 기호가 아닌 숫자를 입력했는데 경고문이 나오지 않고 두 번째 숫자 입력으로 넘어가버렸다. 게다가 잘못된 연산결과인데도 그걸 기록으로 저장하다니.. 말도 안되는 예외였다.

어쨋든 잘 입력만 하면 계산은 잘되는데..?

 

하지만 예외를 발견한 이상 그냥 넘어갈 수는 없었다. 

System.out.print("연산자를 입력하세요 ( +, -, *, /) : ");
String operator = sc.next("[+\\-*/]");

이런 상황에 try - catch를 쓰면 좋겠지만 아직 try문 예외처리가 익숙하지 않아서 내가 지정해놓은 기호가 아닌 다른 문자나 숫자가 입력되면 프로그램이 종료되도록 했다. 반복문이나 조건문을 추가해서 예외상황이 발생되면 프로그램을 자동으로 다시 시작할 수 있게되면 좋았겠지만.. 정규표현식을 간단하게나마 쓴 거로 만족했다. (쉽게 쓰는 방법을 알려주신 영빈님 쪽으로 감사인사)

 

↓ 수정한 코드를 실행한 결과보기↓

더보기

계산을 진행하시겠습니까? (Yes or No) : yes
첫 번째 숫자를 입력하세요 : 10
연산자를 입력하세요 ( +, -, *, /) : *
두 번째 숫자를 입력하세요 : 3
계산 결과 : 10*3 = 30
계산 기록 : [30]
계산을 진행하시겠습니까? (Yes or No) : yes
첫 번째 숫자를 입력하세요 : 39
연산자를 입력하세요 ( +, -, *, /) : -
두 번째 숫자를 입력하세요 : 19
계산 결과 : 39-19 = 20
계산 기록 : [30, 20]
계산을 진행하시겠습니까? (Yes or No) : yes
첫 번째 숫자를 입력하세요 : 50
연산자를 입력하세요 ( +, -, *, /) : /
두 번째 숫자를 입력하세요 : 2
계산 결과 : 50/2 = 25
계산 기록 : [30, 20, 25]
계산을 진행하시겠습니까? (Yes or No) : yes
첫 번째 숫자를 입력하세요 : 48
연산자를 입력하세요 ( +, -, *, /) : /
두 번째 숫자를 입력하세요 : 7
계산 결과 : 48/7 = 6
계산 기록 : [30, 20, 25, 6]
계산을 진행하시겠습니까? (Yes or No) : yes
첫 번째 숫자를 입력하세요 : 10
연산자를 입력하세요 ( +, -, *, /) : +
두 번째 숫자를 입력하세요 : 3
계산 결과 : 10+3 = 13
계산 기록 : [30, 20, 25, 6, 13]
계산을 진행하시겠습니까? (Yes or No) : yes
첫 번째 숫자를 입력하세요 : 38
연산자를 입력하세요 ( +, -, *, /) : /
두 번째 숫자를 입력하세요 : 2
계산 결과 : 38/2 = 19
계산 기록 : [20, 25, 6, 13, 19]
계산을 진행하시겠습니까? (Yes or No) : no

코드를 수정하고 연산 기호가 아닌 숫자를 입력했을 때 두 번째 숫자 입력으로 넘어가는지, 잘못된 결과가 저장되진 않는지 테스트해봤다.

결과는 다행히 잘 실행된다. 생각했던 것처럼 예외상황이 나왔을 때 프로그램이 자동으로 재시작되는 건 구현하지 못했지만 나름대로 잘 구현되었다고 생각한다. 계산기 lv3까지 해내고싶었는데, 아직 구멍이 뚫려있는 나의 지식 상태로는 구현해봤자 의미가 없을 것이라고 판단되었다. 앞으로 주어진 시간을 더 알차게 써서 구멍난 지식을 메우고 나면 꼭 구현해봐야지!

 

<문제점>

- 연산기호가 아닌 문자나 숫자를 입력했을 때 경고문자나 에러 알림이 뜨지 않고 두 번째 입력으로 넘어감

- 잘못된 연산자나 숫자를 입력해도 계산을 진행해 잘못된 결과를 저장하고 불러옴

 

<해결방안, 개선점>

- lv1에서 아쉬웠던 종료조건을 프로그램 시작할 때 넣어 사용자가 yes를 입력하면 계산이 진행되고 no를 입력하면 종료되게 함

- 연산자를 입력받는 next() 에 정규표현식을 이용해 지정한 연산자가 아니면 프로그램을 강제 종료시킴

- 강제 종료 전 입력된 데이터는 저장되지 않음

 

<아쉬운 점>

- 예외를 따로 처리해 프로그램이 종료되지 않고 다시 자동으로 시작되는 것을 구현하지 못함