🔌 SPARTA/Assignments

[Java] 계산기 과제 2회차 : 1회차와의 차이점(2)

eunjiom 2026. 1. 21. 17:16

🗒️ 플로우차트

1단계: if문 기초

  • 요일을 입력 받아 평일/주말 판별하기

 

2단계: if문 응용 + 중첩

  • 학점계산기(A~F등급)


2️⃣ Step 2

1. 사칙연산 수행 후 결과값 반환

  • 1회차
    public int calculator(int a, int b, char op) { 
    // 매개변수에 사칙연산 같이 입력
    
        int result = 0;

        switch (op) {
            case '+':
                result = a + b;
                break;

            case '-':
                result = a - b;
                break;

            case '*':
                result = a * b;
                break;

            case '/':
                if (b == 0) {
                    System.out.println("b에 0을 입력할 수 없습니다");
                    return  0;
                }
                result = a / b;
                break;

            default:
                System.out.println("잘못된 연산자 입니다.");
                return 0;

        }

        return result;
  • 2회차
        int result = 0;

        switch (op) {
            case '+' -> result = a + b;
            case '-' -> result = a - b;
            case '*' -> result = a * b;
            case '/' -> {
                if (b == 0) {
                    throw new ArithmeticException("0으로 나눌 수 없습니다.");
                }
                result = a / b;
            }

            default -> throw new IllegalArgumentException("잘못된 연산자 입니다.");

        }

 

ㄴ throw를 통해 예외처리 진행

 

2. while 조건 직관적으로 변경

  • 1회차
        int i = 1;
        while (i < 2) {
        .
        .
        .
 	}
    
            {
            System.out.print("더 진행하시겠습니까? (exit 입력 시 종료): ");
            String exit =  sc.nextLine();

            if (exit.equals("exit"))
                 i = 2;

            }
  • 2회차
        while (!exit.equals("exit")) { // exit가 아닐 때 반복
        .
        .
           System.out.println("결과 ="+ result);
           System.out.println("종료를 원하면 exit 입력");
           exit = sc.nextLine();

 

3. 캡슐화 / 간접접근

  • 1회차
 private ArrayList<Integer> names = new ArrayList<>()
 
 .
 .
 .
 
       names.add(result); // 결과 기록
        return result;
  • 2회차
    private final ArrayList<Integer> results = new ArrayList<>();
     .
 .
 .
 
        results.add(result);
        return result;

 

ㄴ 튜터님의 피드백을 받아 변수명을 직관적으로 변경 / final를 사용하여 저장된 결과 리스트 변경X > 게터로 읽기만 가능

ㄴ final 을 사용하므로 간접변경을 도와주는 setter 삭제

 

4. 아쉬운 점 반영

  • 1회차
            int result = calculator.calculator(a, b, op);
            System.out.println("결과 = " + result);

            // 종료안내
            System.out.print("더 진행하시겠습니까? (exit 입력 시 종료): ");
            String exit = sc.nextLine();

            if (exit.equals("exit"))
                i = 2;

        }

        // getter
        ArrayList<Integer> newResult = calculator.getResult();
        System.out.println(" # 저장된 결과 조회: "+ newResult);

        // 먼저 저장된 결과 삭제하기
        System.out.print("먼저 저장된 결과를 삭제할까요?(yes or no): ");
        String remove = sc.nextLine();

        if (remove.equals("yes")) {
            calculator.removeResult();
        }
  • 2회차
            int result = calculator.calculator(a, b, op);

            System.out.println("결과 =" + result);

            System.out.println("현재 저장된 결과"+ calculator.getResult());

            System.out.println("가장 먼저 저장된 결과를 삭제하시겠습니까? yes or no");
            String answer = sc.nextLine();
            if("yes".equals(answer)){
                calculator.removeResult();
                System.out.println("가장 먼저 저장된 결과 삭제 후: "+calculator.getResult());
            }

            System.out.println("종료를 원하면 exit 입력");
            exit = sc.nextLine();

        }

        System.out.println("계산기 종료");
        sc.close();

 

ㄴ 1회차 때 아쉬웠던 점을 보완하여 exit 입력 전에 저장된 결과를 조회할 수 있고 삭제할 수 있음 / 삭제 후 결과도 조회 가능

3️⃣ Step 3

1. enum 타입을 활용하여 연산자 타입 정보를 관리 >  ArithmeticCalculator 클래스에 활용

  • enum: 미리 정해둔 선택지 목록 / 미리 정해진 것만 고를 수 있음
  • enum 클래스
public enum OperatorType {

    ADD('+'),
    SUB('-'),
    MUL('*'),
    DIV('/');

    private final char symbol;

    OperatorType(char symbol){
        this.symbol = symbol;
    }

    // 문자 > enum으로 사용 / new 없이 static으로 사용
    public static OperatorType fromchar(char op){
        // 입력 값이 op와 같다면 값을 리턴
        for (OperatorType op2: values()){
            if(op2.symbol == op){
                return op2;
            }
        }
        throw new IllegalArgumentException("잘못된 연산자 입니다.");
    }
}

 

  • ArithmeticCalculator 클래스
import java.util.ArrayList;

public class ArithmeticCalculator {

    private final ArrayList<Integer> results = new ArrayList<>();

    public int calculator(int a, int b, char op) {

        int result;
        // op와 일치하는 enum 값을 가져옴
        OperatorType operatorType = OperatorType.fromchar(op);

        switch (operatorType) {
            case ADD -> result = a + b;
            case SUB -> result = a - b;
            case MUL -> result = a * b;
            case DIV -> {
                if (b == 0) {
                    throw new ArithmeticException("0으로 나눌 수 없습니다.");
                }
                result = a / b;
            }

            default -> throw new IllegalArgumentException("잘못된 연산자 입니다.");

        }

        results.add(result);
        return result;

    }

    // getter
    public ArrayList<Integer> getResult() {
        return results;
    }

    public void removeResult() {
        results.remove(0);
        }
    }
  • Main
public class Main {

    static void main() {

        Scanner sc = new Scanner(System.in);
        // 변수 변경
        ArithmeticCalculator calculator = new ArithmeticCalculator();
        String exit = ""; // exit 입력 시 종료

        // 반복문 사용
        while (!exit.equals("exit")) { // exit가 아닐 때 반복
            // 숫자값 입력받기
            System.out.print("첫번째 숫자를 입력하세요: ");
            int a = Integer.parseInt(sc.nextLine());

            // 0을 포함한 양의 정수값만 입력받기
            if (a < 0) {
                System.out.println("0을 포함한 양의 정수만 입력 가능합니다");
                return;
            }

            System.out.print("두번째 숫자를 입력하세요: ");
            int b = Integer.parseInt(sc.nextLine());

            if (b < 0) {
                System.out.println("0을 포함한 양의 정수만 입력 가능합니다");
                return;
            }

            System.out.println("a:" + a + "\n b:" + b);

            // 사칙연산 기호 입력받기
            System.out.print("사칙연산을 입력하세요(+, -, *, /): ");
            char op = sc.nextLine().charAt(0);

            int result = calculator.calculator(a, b, op);

            System.out.println("결과 =" + result);

            System.out.println("현재 저장된 결과" + calculator.getResult());

            System.out.println("가장 먼저 저장된 결과를 삭제하시겠습니까? yes or no");
            String answer = sc.nextLine();
            if ("yes".equals(answer)) {
                calculator.removeResult();
                System.out.println("가장 먼저 저장된 결과 삭제 후: " + calculator.getResult());
            }

            System.out.println("종료를 원하면 exit 입력");
            exit = sc.nextLine();

        }

        System.out.println("계산기 종료");
        sc.close();

    }
}

 

2. double 타입 값 전달받기

  • 제네릭을 활용해 여러 타입 받을 수 있도록 기능 확장
  • enum 클래스
    public abstract double apply(double a, double b);
  • ArithmeticCalculator 클래스
    // 제네릭 더블타입으로 변경
    private final ArrayList<Double> results = new ArrayList<>();

    // 더블도 되고 int도 됨
    public <T extends Number, U extends Number> double calculator(T a, U b, OperatorType op) {

        double double1 = a.doubleValue();
        double double2 = b.doubleValue();
        double result = op.apply(double1, double2);


        results.add(result);
        return result;

    }
  • Main
        while (!exit.equals("exit")) { // exit가 아닐 때 반복
            System.out.print("첫번째 숫자를 입력하세요: ");
            // 여러가지 타입을 받기 위해 문자열 사용
            String input1 = sc.nextLine();
            // 소수 점이 있으면 더블타입, 아니면 int 타입
            Number a = input1.contains(".") ? Double.parseDouble(input1) : Integer.parseInt(input1);

            System.out.print("두번째 숫자를 입력하세요: ");
            String input2 = sc.nextLine();
            Number b = input2.contains(".") ? Double.parseDouble(input2) : Integer.parseInt(input2);


            System.out.print("사칙연산을 입력하세요(+, -, *, /): ");
            char op = sc.nextLine().charAt(0);
            OperatorType operatorType = OperatorType.fromchar(op);

            double result = calculator.calculator(a, b, operatorType);

 

3. 특정 값보다 큰 결과값 출력하기

  • 람다와 스트림 활용하여 기능확장
  • ArithmeticCalculator 클래스에 조회 메서드 구현
    // 특정 값보다 큰 결과 조회
    public List<Double> getResultsGreaterThan(double threshold){
        return results.stream() //리스트 값을 펼친다
                .filter(v -> v > threshold) // 입력 값보다 큰 경우
                .collect(Collectors.toList());
}
  • Main
            System.out.println("특정 값보다 큰 결과를 조회하시겠습니까? yes or no:");
            String query = sc.nextLine();
            if("yes".equals(query)){
                System.out.println("기준 값을 입력하세요: ");
                double threshold = Double.parseDouble(sc.nextLine());
                System.out.println("기준보다 큰 결과: " +calculator.getResultsGreaterThan(threshold));

 

✅ README

더보기

1️⃣ Step 1

 

1. 프로젝트 소개

  • Java 문법을 이용하여 class를 생성하지 않고 main 내에서 사칙연산을 가능하게 한 계산기입니다.
    사용자가 두 개의 정수와 사칙연산을 입력하면 계산되어 결과값이 나옵니다.
    exit를 이용하여 계산을 종료할 수 있습니다.

2. 주요 기능

  • 사칙연산(+, -, *, /) 수행
  • 0으로 나누는 경우 예외처리
  • 잘못된 연산자 입력시 오류 문구 출력
  • exit 입력시 계산 반복 종료

3. 이용방법

  • main 클래스를 실행합니다.
  • 첫번째 숫자를 입력합니다.
  • 두번째 숫자를 입력합니다.
  • 사칙연산 기호를 입력합니다. (+, -, *, /)
  • 결과값을 확인합니다.
  • " 더 진행하시겠습니까? (exit 입력 시 종료): " 문구가 나왔을 때,
    계속 진행할 경우 아무 텍스트나 입력하고 종료하시려면 exit를 입력합니다.

4. 예외처리

  • 사칙연산 외 텍스트나 숫자 입력 시 오류 문구 및 결과 0 출력
  • 0으로 나누는 경우 오류 문구 및 결과 0 출력

5. 흐름(플로우차트)


2️⃣ Step 2

 

1. 프로젝트 소개

  • Step 1 계산기를 기반으로 클래스를 분리하여 역할을 나눈 계산기입니다.
    Calculator 클래스에서 연산을 수행하고, 연산 결과를 컬렉션에 저장하도록 구현했습니다.
    저장된 연산 결과를 조회하거나 가장 먼저 저장된 결과를 삭제할 수 있습니다.

2. 주요 기능

  • 사칙연산(+, -, *, /) 수행
  • 0으로 나누는 경우 예외 처리
  • 잘못된 연산자 입력 시 오류 문구 출력
  • exit 입력 시 계산 반복 종료
  • 연산 결과를 컬렉션(ArrayList)에 저장
  • 저장된 연산 결과 조회 기능
  • 가장 먼저 저장된 연산 결과 삭제 기능

3. 클래스 구성

  • Calculator 클래스
    • 사칙연산 수행 기능
    • 연산 결과를 저장하는 컬렉션 필드 보유
    • Getter / Setter를 통해 연산 결과 간접 접근
    • 가장 먼저 저장된 연산 결과 삭제 기능 제공
  • Main 클래스
    • 사용자 입력 처리
    • Calculator 객체를 생성하여 연산 기능 사용
    • 연산 결과 출력 및 프로그램 반복 제어

4. 이용 방법

  • Main 클래스를 실행합니다.
  • 첫 번째 숫자를 입력합니다.
  • 두 번째 숫자를 입력합니다.
  • 사칙연산 기호를 입력합니다. (+, -, *, /)
  • 계산 결과를 확인합니다.
  • "더 진행하시겠습니까? (exit 입력 시 종료)" 문구가 나오면
    계속 진행할 경우 아무 텍스트나 입력하고, 종료하려면 exit를 입력합니다.
  • 프로그램 종료 후 저장된 연산 결과가 출력됩니다.
  • 가장 먼저 저장된 결과를 삭제할지 여부를 선택할 수 있습니다.

5. 캡슐화 적용

  • 연산 결과를 저장하는 컬렉션 필드를 private으로 선언하여 외부 접근을 제한했습니다.
  • Getter 메서드를 통해 저장된 결과를 조회할 수 있도록 구현했습니다.
  • Setter 메서드를 통해 컬렉션을 수정할 수 있도록 구현했습니다.

6. 예외 처리

  • 0으로 나누는 경우 오류 문구 출력 후 결과 0 반환
  • 사칙연산 기호 외 입력 시 오류 문구 출력 후 결과 0 반환

7. 흐름(플로우)

8. 변경된 점

  • 변수명을 직관적으로 변경(names > results)
  • while 조건 직관적으로 변경(exit 입력시 종료, 아니면 반복)
  • exit 입력 전에 저장된 결과 조회 및 삭제 가능
  • final로 저장결과 리스트를 보호하여 getter로는 읽기만 가능 / setter 삭제
  • throw로 예외처리

3️⃣ Step 3

 

1. 프로젝트 소개

Step 3에서는 Step 2 계산기를 확장하여
Enum, 제네릭, 람다 & 스트림을 활용한 계산기를 구현했습니다.

기존에는 양의 정수(int)만 연산이 가능했지만,
이번 단계에서는 정수와 실수(double)를 모두 처리할 수 있도록 개선했습니다.
또한 사칙연산 기호를 Enum으로 관리하고,
저장된 연산 결과를 특정 조건에 따라 조회할 수 있도록 기능을 추가했습니다.

2. 주요 기능

  • 사칙연산(+, -, *, /) 수행 (Enum 기반)
  • 정수(int)와 실수(double) 연산 지원 (제네릭 사용)
  • 0으로 나누는 경우 예외 처리
  • 잘못된 연산자 입력 시 예외 발생
  • 연산 결과를 컬렉션(ArrayList)에 저장
  • 가장 먼저 저장된 연산 결과 삭제 기능
  • 저장된 연산 결과 중 특정 값보다 큰 결과 조회
  • Lambda & Stream을 활용한 결과 필터링
  • exit 입력 시 계산 반복 종료

3. 클래스 구성

  • OperatorType (Enum)
    • 사칙연산 타입을 Enum으로 관리
    • 각 연산자는 기호(+ - * /)와 연산 로직을 함께 보유
    • apply() 메서드를 추상 메서드로 선언하여 각 연산에서 강제 구현
    • 입력받은 문자(char)를 Enum으로 변환하는 fromChar() 메서드 제공
  • ArithmeticCalculator
    • 연산 결과를 저장하는 ArrayList 컬렉션 보유
    • 제네릭(<T extends Number, U extends Number>)을 사용하여
    • 정수와 실수 타입 모두 연산 가능
    • Enum의 apply() 메서드를 이용해 연산 수행
    • 연산 결과를 컬렉션에 저장
    • 가장 먼저 저장된 결과 삭제 기능 제공
    • Lambda & Stream을 활용한 결과 조회 기능 제
  • Main
    • 사용자 입력 처리
    • 문자열 입력을 통해 정수 / 실수 구분 처리
    • ArithmeticCalculator 객체 생성 및 연산 요청
    • 연산 결과 출력
    • 저장된 결과 조회 및 삭제 여부 선택
    • 특정 값보다 큰 결과 조회 기능 실행
    • exit 입력 시 프로그램 종료

4. 이용 방법

  • Main 클래스를 실행합니다.
  • 첫 번째 숫자를 입력합니다. (정수 또는 실수)
  • 두 번째 숫자를 입력합니다. (정수 또는 실수)
  • 사칙연산 기호를 입력합니다. (+, -, *, /)
  • 계산 결과를 확인합니다.
  • 현재 저장된 연산 결과를 확인합니다.
  • 가장 먼저 저장된 결과를 삭제할지 선택합니다.
  • 특정 값보다 큰 결과를 조회할지 선택합니다.
  • 종료를 원할 경우 exit를 입력합니다.

5. 제네릭 적용

  • ArithmeticCalculator의 연산 메서드에 제네릭을 적용하여 int, double 등 다양한 숫자 타입을 받을 수 있도록 구현했습니다.
  • Number 클래스를 상속받는 타입으로 제한하여 안전하게 doubleValue()를 사용해 연산했습니다.

6. 람다 & 스트림 적용

  • 저장된 연산 결과를 조회할 때 Stream API 사용
  • filter()를 이용해 특정 값보다 큰 결과만 추출
  • collect(Collectors.toList())로 결과 리스트 반환