- 
                Notifications
    You must be signed in to change notification settings 
- Fork 155
[4기 - 김영훈] 1~2주차 과제: 계산기 구현 미션 제출합니다. #163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: b2sic
Are you sure you want to change the base?
Changes from 16 commits
aa3cbc6
              7e4578f
              6368d93
              a37c6cd
              18c4dbc
              339bac9
              2dcd810
              b0839b6
              39ff8c7
              9cb8ce8
              6cbe184
              616e910
              a119b9e
              03389be
              45abcdc
              dd6f3bc
              5305130
              2a7acd7
              88049e0
              54792dd
              f3c524e
              2cc308c
              6fbb043
              aae2a9e
              5edf79d
              2464e92
              4e58371
              4167cfc
              9e06b24
              3037564
              4f30930
              5b23467
              5dcd2aa
              99f6ce7
              ac8794f
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import computation.PostfixComputer; | ||
| import computation.PostfixConverter; | ||
| import io.Calculator; | ||
| import repository.CalculatorHistoryRepository; | ||
|  | ||
| import java.io.IOException; | ||
|  | ||
| public class CalculatorApplication { | ||
| public static void main(String[] args) throws IOException { | ||
| Calculator calculator = new Calculator(new PostfixConverter(), new PostfixComputer(), new CalculatorHistoryRepository()); | ||
| calculator.runApplication(); | ||
| } | ||
| } | 
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package computation; | ||
|  | ||
| import java.util.List; | ||
|  | ||
| public interface Converter { | ||
| List<String> convert(String expression); | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package computation; | ||
|  | ||
| import exception.ZeroDivisionException; | ||
| import java.util.Arrays; | ||
| import java.util.function.BiFunction; | ||
|  | ||
| public enum Operator { | ||
| ADD("+", (num1, num2) -> num1 + num2), | ||
| SUBTRACT("-", (num1, num2) -> num1 - num2), | ||
| MULTIPLY("*", (num1, num2) -> num1 * num2), | ||
| DIVIDE("/", (num1, num2) -> { | ||
| if (num2 == 0) | ||
| throw new ZeroDivisionException(); | ||
| return num1 / num2; | ||
| }); | ||
|  | ||
| private final String operator; | ||
| private final BiFunction<Integer, Integer, Integer> expression; | ||
|  | ||
| Operator(String operator, BiFunction<Integer, Integer, Integer> expression) { | ||
| this.operator = operator; | ||
| this.expression = expression; | ||
| } | ||
|  | ||
| public static Operator getOperator(String getString) { | ||
| return Arrays.stream(Operator.values()) | ||
| .filter(s -> s.operator.equals(getString)) | ||
| .findFirst() | ||
| .get(); | ||
| } | ||
|  | ||
| public int operate(Integer num1, Integer num2) { | ||
| return expression.apply(num1, num2); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package computation; | ||
|  | ||
| import validation.Validator; | ||
|  | ||
| import java.util.List; | ||
| import java.util.Stack; | ||
|  | ||
| public class PostfixComputer { | ||
| public int calculate(List<String> postfixExpression) { | ||
| Stack<Integer> calculationStack = new Stack<>(); | ||
|  | ||
| for (String item : postfixExpression) { | ||
| if (Validator.isNumber(item)) { | ||
| calculationStack.push(Integer.parseInt(item)); | ||
| } else if (Validator.isOperator(item)) { | ||
| Integer operand2 = calculationStack.pop(); | ||
| Integer operand1 = calculationStack.pop(); | ||
|  | ||
| Operator operator = Operator.getOperator(item); | ||
| calculationStack.push(operator.operate(operand1, operand2)); | ||
| } | ||
| } | ||
| return calculationStack.pop(); | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| package computation; | ||
|  | ||
| import validation.Validator; | ||
|  | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Stack; | ||
|  | ||
| public class PostfixConverter implements Converter { | ||
| private final StringBuilder sb = new StringBuilder(); | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stack자료구조와 StringBuilder를 함께 사용하고 있는데요. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. convert 메소드는 입력 받은 문자열을 한글자씩 가져와서 처리를 하는데, 이 때 두 자리 이상의 숫자가 들어오는 경우 | ||
| private final Map<String, Integer> priority = Map.of( | ||
| "(", 0, | ||
| "+", 1, | ||
| "-", 1, | ||
| "*", 2, | ||
| "/", 2 | ||
| ); | ||
|  | ||
| private boolean checkHigherPriority(Stack<String> operatorStack, String item) { | ||
| return priority.get(operatorStack.peek()) >= priority.get(item); | ||
| } | ||
|  | ||
| public void addElement(List<String> list) { | ||
| if (sb.length() > 0) { | ||
| list.add(sb.toString()); | ||
| sb.setLength(0); | ||
| } | ||
| } | ||
|  | ||
| @Override | ||
| public List<String> convert(String expression) { | ||
| List<String> postfix = new ArrayList<>(); | ||
|  | ||
| Stack<String> operatorStack = new Stack<>(); | ||
| String[] infixArray = expression.split(""); | ||
| sb.setLength(0); | ||
|  | ||
| for (int i = 0; i < infixArray.length; i++) { | ||
| // 숫자라면 단순히 추가 | ||
| if (Validator.isNumber(infixArray[i])) { | ||
| sb.append(infixArray[i]); | ||
|  | ||
| if (i == infixArray.length - 1) { | ||
| postfix.add(sb.toString()); | ||
| } | ||
| } else { | ||
| addElement(postfix); | ||
|  | ||
| if (Validator.isOperator(infixArray[i])) { | ||
| // 연산자라면 먼저 우선순위 계산 | ||
| if (!operatorStack.isEmpty()) { | ||
| while (!operatorStack.isEmpty() && checkHigherPriority(operatorStack, infixArray[i])) { | ||
| postfix.add(operatorStack.pop()); | ||
| } | ||
| } | ||
| operatorStack.push(infixArray[i]); | ||
| } else if (Validator.isOpenBrackets(infixArray[i])) { | ||
| operatorStack.push(infixArray[i]); | ||
| } else if (Validator.isCloseBrackets(infixArray[i])) { | ||
| // 괄호에 대한 처리 | ||
| while (!operatorStack.isEmpty()) { | ||
| String poppedItem = operatorStack.pop(); | ||
| if (Validator.isOpenBrackets(poppedItem)) break; | ||
| postfix.add(poppedItem); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|  | ||
| while (!operatorStack.isEmpty()) { | ||
| postfix.add(operatorStack.pop()); | ||
| } | ||
| return postfix; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package exception; | ||
|  | ||
| public class ZeroDivisionException extends RuntimeException { | ||
| private static final String MESSAGE = "0으로는 나눌 수 없습니다."; | ||
| public ZeroDivisionException() { | ||
| super(MESSAGE); | ||
| } | ||
| } | 
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| package io; | ||
|  | ||
| import computation.Converter; | ||
| import computation.PostfixComputer; | ||
| import exception.ZeroDivisionException; | ||
| import repository.Repository; | ||
| import util.StringUtil; | ||
| import validation.Validator; | ||
|  | ||
| import java.io.BufferedReader; | ||
| import java.io.IOException; | ||
| import java.io.InputStreamReader; | ||
|  | ||
| public class Calculator { | ||
| private final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. View객체를 따로 구현하지 않은 이유가 있을까요?? (정말 몰라서 여쭤보는 겁니다!) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 특별한 이유는 없고 View 객체가 무엇을 의미하는지 조금 헷갈려서 제대로 분리하지 못한 것 같습니다 😢 | ||
| private final Converter converter; | ||
| private final PostfixComputer calculator; | ||
| private final Repository repository; | ||
|  | ||
| public Calculator(Converter converter, PostfixComputer calculator, Repository repository) { | ||
| this.converter = converter; | ||
| this.calculator = calculator; | ||
| this.repository = repository; | ||
| } | ||
|  | ||
| public void printMenu() { | ||
| System.out.println(MenuMessage.SELECT.getMessage()); | ||
| System.out.println(MenuMessage.CALCULATION.getMessage()); | ||
| System.out.println(MenuMessage.EXIT.getMessage()); | ||
| System.out.print(MenuMessage.CHOOSE.getMessage()); | ||
| } | ||
|  | ||
| public String getUserInput() throws IOException { | ||
| return br.readLine(); | ||
| } | ||
|  | ||
| public void runInquiry() { | ||
| System.out.println(DisplayMessage.SPLIT_LINE.getMessage()); | ||
| repository.inquiry(); | ||
| System.out.println(DisplayMessage.SPLIT_LINE.getMessage()); | ||
| } | ||
|  | ||
| public void runCalculator() throws IOException { | ||
| String getInput = StringUtil.removeWhiteSpace(getUserInput()); | ||
| if (!Validator.isRightExpression(getInput)) { | ||
| System.out.println(DisplayMessage.WRONG_EXPRESSION.getMessage()); | ||
| return; | ||
| } | ||
|  | ||
| try { | ||
| int result = calculator.calculate(converter.convert(getInput)); | ||
| repository.save(getInput, result); | ||
| System.out.print(DisplayMessage.OUTPUT.getMessage()); | ||
| System.out.println(result); | ||
| } catch (ZeroDivisionException e) { | ||
| System.out.println(e.getMessage()); | ||
| } | ||
| } | ||
|  | ||
|  | ||
| public void runApplication() throws IOException { | ||
| while (true) { | ||
| printMenu(); | ||
|  | ||
| String getChoice = getUserInput(); | ||
| if (Validator.isNotNumber(getChoice)) { | ||
| System.out.println(DisplayMessage.BAD_REQUEST.getMessage()); | ||
| continue; | ||
| } | ||
|  | ||
| int choice = Integer.parseInt(getChoice); | ||
| if (choice == Menu.QUERY.getMenuNumber()) { | ||
| // 조회 | ||
| runInquiry(); | ||
| } else if (choice == Menu.CALCULATE.getMenuNumber()) { | ||
| // 계산 | ||
| runCalculator(); | ||
| } else if (choice == Menu.EXIT.getMenuNumber()) { | ||
| // 종료 | ||
| System.exit(0); | ||
| } else { | ||
| System.out.println(DisplayMessage.BAD_REQUEST.getMessage()); | ||
| } | ||
| 
      Comment on lines
    
      +71
     to 
      +83
    
   There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Menu Enum에 저장되어 있는 값을 꺼내서 비교하지 말고 입력받은 값을 Menu로 파싱한 다음 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 값을 직접 꺼내서 비교하는 것보다 입력 값을 파싱을 통해 비교하도록 하는게 Enum을 더 효과적으로 쓰는 방법이 되겠네요! | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getString이라는 네이밍보다는operator라는 네이밍이 좀 더 자연스러울 것 같아요.자바에서 변수는 명사를 주로 사용합니다!
참고자료 : https://tecoble.techcourse.co.kr/post/2020-04-24-variable_naming/
추가로 Optional.get()을 이용해서 객체를 꺼내주고 있는데요. 만약 �이상한 값이 들어오면
null이 반환될 것 같아요.Optional에 대해 공부해보시면 좋을 것 같아요!참고자료 : https://www.daleseo.com/java8-optional-before/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아하 그렇군요! 네이밍에 조금 더 신경을 써야 할 것 같습니다.
Optional에 대한 공부 자료도 감사합니다!