[project]Calculator_5

기 원·2025년 2월 27일

계산기 개발에 필요한 필수 조건과 도전 조건을 충족한
계산기 구현 프로그램 제작.

필수 조건
1. 양의 정수 입력받기
2. 사칙연산 기호 입력받기
3. 입력받은 데이터를 바탕으로 연산 수행 후 결과물 출력
4. "exit"문자열을 입력하기 전까지 무한으로 동작
5. 연산을 수행 후, 결과값 반환 메서드 구현 & 연산 결과를 저장하는 컬렉션 타입 필드를 가진 Calculator 클래스 생성
7. Calculator에서 저장한 결과를 직접 접근하지 못하도록 수정(캡슐화)
8. 저장된 데이터 중 가장 먼저 저장된 데이터를 삭제하는 기능
9. 사칙연산 기호를 Enum으로 관리
10. 실수 타입의 값을 전달 받으면 데이터 타입을 변경 후 연산

  1. 저장된 연산 결과 중 입력한 값보다 큰 값을 출력하는 기능

Main.java

public class Main {
    public static void main(String[] args) {
        App.main(args);
    }
}

App.java

import java.util.List;
import java.util.Objects;
import java.util.Scanner;

public class App {
    public static void main(String[] args) {

        //Calculator 호출
        Calculator<Number> calculator = new Calculator();

        //Scanner 활성화
        Scanner sc = new Scanner(System.in);

        //무한 반복을 위한 for 문
        for (int i = 1; ; i++) {
            System.out.printf("\n========계산 준비 완료 / 사용량 : %d회==========\n\n", i-1);

            //연산을 위한 값 입력받기
            Number fstVal = getdataval(sc, "첫번째 숫자를 입력하세요.");
            System.out.println();
            OperatorType operatortype = getdatasymol(sc, "사칙연산 기호를 입렵하세요(+, -, *, /)");
            Number sndVal = getdataval(sc, "두번째 숫자를 입력하세요.");
            System.out.println();

            //연산 처리(Calculator.java)
            double result = calculator.calculate(fstVal, sndVal, operatortype);
            System.out.printf("결과값 :\n%s %c %s = %s\n\n", fstVal, operatortype.getSymbol(), sndVal, result);


            //getter 를 사용해 데이터 받기
            System.out.println("최근 계산값");
            for (String history : calculator.getHistory()) {
                System.out.println(history);
            }
            System.out.println();

            // 도전 입력값보다 큰값 찾기
            System.out.println("입력값 보다 큰 값을 출력할까요 ( y / n )");
            char yn = sc.next().charAt(0);
            if(yn == 'y'){
                Number Value2 = getdataval(sc, "\n값을 입력 하세요");
                List<Double> result2 = calculator.filterVal(Value2);
                if(result2.isEmpty()){
                    System.out.println("\n목록");
                    System.out.println("=========");
                    System.out.println();
                    System.out.println("=========");
                } else {
                    System.out.println("\n목록");
                    System.out.println("=========");
                    result2.forEach(System.out::println);
                    System.out.println("=========");
                }
            }

            //종료 문구 확인
            System.out.println("종료 하시려면 'exit'를 입력해주세요: ");
            String out = sc.next();
            if (Objects.equals(out, "exit")){
                break;
            }
        }
        //Scanner 비활성화
        sc.close();
    }

    //정수 입력받기 매서드 // 제네릭 활용 데이터 타입 변환
    private static <T extends Number> T getdataval(Scanner sc, String msg){
        System.out.println(msg);
        System.out.print(": ");

        while (true){
            String input = sc.next();
            try{
                if(input.contains(".")){
                    return (T) Double.valueOf(input);
                } else {
                    return (T) Integer.valueOf(input);
                }
            } catch (NumberFormatException e){
                System.out.println("잘못된 값을 입력하였습니다.");
                System.out.print(": ");
            }
        }
    }

    // 기호 입력받기 매서드
    private static OperatorType getdatasymol(Scanner sc, String msg){
        System.out.println(msg);
        System.out.print(": ");
        while(true){
            String input = sc.next();
            System.out.println();
            if(input.length() == 1){
                char symbol = input.charAt(0);
                try {
                    return OperatorType.getOperatorType(symbol);
                } catch (IllegalArgumentException e){
                    System.out.println(e.getMessage());
                    System.out.print(": ");
                }
            }
        }
    }
}

Calculator.java

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Calculator<T extends Number> {
    private List<String> history; //정보 은닉
    private static final int maxSize = 10;


    public Calculator() {
        this.history = new ArrayList<>();
    }

    //연산
    public double calculate(T fstVal, T sndVal, OperatorType operator) {
        double result = 0;
        String savedata;

        double fstValDouble = fstVal.doubleValue();
        double sndValDouble = sndVal.doubleValue();

        switch (operator) {
            case add:
                result = fstValDouble + sndValDouble;
                break;
            case sub:
                result = fstValDouble - sndValDouble;
                break;
            case mul:
                result = fstValDouble * sndValDouble;
                break;
            case div:
                if (sndValDouble == 0) {
                    System.out.println("분모에는 0이 들어갈 수 없습니다." + "\n");
                    return 0;
                }
                result = fstValDouble / sndValDouble;
                break;
        }
        //필수 LV2 setter 사용 데이터 저장
        savedata = fstVal + " " + operator.getSymbol() + " " + sndVal + " = " + result;
        setHistory(savedata); //setHistory 에서 저장
        return result;
    }

    // 필수 LV2 데이터 저장
    public void setHistory(String savedata){
        history.add(savedata);
        removeresult();
    }

    // 필수 LV2 getter 사용 데이터 반환
    public List<String> getHistory() {
        return new ArrayList<>(history);
    }

    // 필수 LV2 오래된 데이터 삭제
    public void removeresult(){
        if(history.size() > maxSize) {
            history.remove(0);
        }
    }

    // 도전 람다 & 스트림을 사용한 입력한 값보다 큰 결과값 출력
    public double extractVal(String history){
        String[] parts = history.split(" = ");
        try{
            return Double.parseDouble(parts[1].trim());
        } catch (NumberFormatException e){
            return 0;
        }
    }

    public List<Double>filterVal(Number value){
        return history.stream().map(this::extractVal)
                .filter(num -> num > value.doubleValue())
                .collect(Collectors.toList());
    }

}

OperatorType

//도전과제 Enum 구현
public enum OperatorType {
    add('+'), sub('-'), mul('*'), div('/');

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

    public char getSymbol() {
        return symbol;
    }

    //입력 받은 기호와 해당하는 Enum 찾기
    public static OperatorType getOperatorType(char symbol) {
        for (OperatorType operatorType : OperatorType.values()) {
            if (operatorType.getSymbol() == symbol) {
                return operatorType;
            }
        }
        throw new IllegalArgumentException("연산 기호를 확인해주세요");
    }
}
profile
노력하고 있다니까요?

0개의 댓글