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