-
Notifications
You must be signed in to change notification settings - Fork 155
[4기 - 한승원] 1~2주차 과제 : 계산기 구현 미션 제출합니다(사칙연산) #168
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: seungwon
Are you sure you want to change the base?
Changes from 11 commits
2f8bb46
5a6deed
c4c3e88
e2dcb42
bd3aee3
52a1300
ee4d032
842467d
c9c80e0
25a513e
6d94091
4d764ca
882c684
1a150a5
a3901a5
451742e
775466d
5e41f40
2590e8c
6b66bc0
2f88ba9
f154103
ddc919c
9b34581
9b943b9
c6c5a68
6d43a13
97b393a
84540a2
eeb3796
c37cdad
50cabb1
0ac007e
8b4ec3a
a3544d8
ea158fe
6f1519d
7fe46d5
aa52739
202ce5d
716fb12
c2351bd
1f42c10
358117c
f635ecb
06b76d3
84ff197
49675ef
62afa70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package co.programmers.application; | ||
|
|
||
| import co.programmers.view.CalculatorInputView; | ||
| import co.programmers.view.CalculatorOutputView; | ||
| import co.programmers.view.InputView; | ||
| import co.programmers.view.OutputView; | ||
|
|
||
| public class Application { | ||
|
|
||
| public static void main(String[] args) { | ||
| InputView inputView = new CalculatorInputView(); | ||
| OutputView outputView = new CalculatorOutputView(); | ||
| Calculator calculator = new Calculator(inputView, outputView); | ||
| calculator.run(); | ||
| } | ||
| } | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| package co.programmers.application; | ||
|
|
||
| import co.programmers.domain.Operator; | ||
| import co.programmers.domain.UserMenu; | ||
| import co.programmers.view.InputView; | ||
| import co.programmers.view.OutputView; | ||
| import java.util.Stack; | ||
|
|
||
| public class Calculator { | ||
|
|
||
| private final InputView inputView; | ||
| private final OutputView outputView; | ||
|
|
||
| public Calculator(InputView inputView, OutputView outputView) { | ||
| this.inputView = inputView; | ||
| this.outputView = outputView; | ||
| } | ||
|
|
||
| public void run() { | ||
| while (true) { | ||
|
||
| UserMenu userMenu = UserMenu.get(inputView.inputUserMenu()); | ||
| switch (userMenu) { | ||
| case INQUIRY: | ||
| // 구현 예정 | ||
| break; | ||
| case CALCULATE: | ||
| String expression = inputView.inputExpression(); | ||
| Integer output = calculate(expression); | ||
| outputView.print(String.valueOf(output)); | ||
|
||
| break; | ||
| case TERMINATE: | ||
| return; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private Integer calculate(String input) { | ||
| char[] expression = input.toCharArray(); | ||
|
||
| Stack<Integer> Operands = new Stack<>(); | ||
| Stack<Character> Operators = new Stack<>(); | ||
|
||
| for (int i = 0; i < expression.length; i++) { | ||
| if (Character.isWhitespace(expression[i])) { | ||
| continue; | ||
| } | ||
| if (Character.isDigit(expression[i])) { | ||
| StringBuffer operand = new StringBuffer(); | ||
| while (i < expression.length && Character.isDigit(expression[i])) { | ||
| operand.append(expression[i++]); | ||
| } | ||
| i--; | ||
| Operands.push(Integer.parseInt(operand.toString())); | ||
| } else if (expression[i] == '(') { | ||
| Operators.push(expression[i]); | ||
| } else if (expression[i] == ')') { | ||
| evaluateOperators(Operands, Operators); | ||
|
||
| } else { | ||
| while (!Operators.empty() && comparePriority(expression[i], Operators.peek())) { | ||
| Operands.push(Operator.calculate( | ||
| String.valueOf(Operators.pop()), Operands.pop(), Operands.pop() | ||
| )); | ||
| } | ||
| Operators.push(expression[i]); | ||
| } | ||
|
||
| } | ||
|
||
| evaluateOperators(Operands, Operators); | ||
| return Operands.pop(); | ||
| } | ||
|
|
||
| private void evaluateOperators(Stack<Integer> operands, Stack<Character> operators) { | ||
| while (!operators.empty() && (operators.peek() != '(')) { | ||
| Character operator = operators.pop(); | ||
| Integer operand1 = operands.pop(); | ||
| Integer operand2 = operands.pop(); | ||
| int result = Operator.calculate( | ||
| String.valueOf(operator), operand1, operand2 | ||
| ); | ||
| operands.push(result); | ||
| } | ||
|
|
||
| if (!operators.empty()) { | ||
| operators.pop(); | ||
| } | ||
| } | ||
|
|
||
| private boolean comparePriority(char operator1, char operator2) { | ||
| return Operator.getSymbol(String.valueOf(operator1)).getPriority() >= | ||
| Operator.getSymbol(String.valueOf(operator2)).getPriority(); | ||
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,60 @@ | ||||||||||||||||||||||
| package co.programmers.domain; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import co.programmers.exception.ExceptionMessage; | ||||||||||||||||||||||
| import java.util.Collections; | ||||||||||||||||||||||
| import java.util.Map; | ||||||||||||||||||||||
| import java.util.Optional; | ||||||||||||||||||||||
| import java.util.function.BiFunction; | ||||||||||||||||||||||
| import java.util.function.Function; | ||||||||||||||||||||||
| import java.util.stream.Collectors; | ||||||||||||||||||||||
| import java.util.stream.Stream; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| public enum Operator { | ||||||||||||||||||||||
| ADDITION("+", 2, (operand1, operand2) -> Integer.valueOf( | ||||||||||||||||||||||
| operand1 + operand2 | ||||||||||||||||||||||
| )), | ||||||||||||||||||||||
| SUBTRACTION("-", 2, (operand1, operand2) -> Integer.valueOf( | ||||||||||||||||||||||
| operand2 - operand1 | ||||||||||||||||||||||
|
||||||||||||||||||||||
| )), | ||||||||||||||||||||||
| MULTIPLICATION("*", 1, (operand1, operand2) -> Integer.valueOf( | ||||||||||||||||||||||
| operand1 * operand2 | ||||||||||||||||||||||
| )), | ||||||||||||||||||||||
| DIVISION("/", 1, (operand1, operand2) -> { | ||||||||||||||||||||||
| if (operand2 == 0) { | ||||||||||||||||||||||
| throw new IllegalArgumentException(ExceptionMessage.DIVIDED_BY_ZERO); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| return Integer.valueOf(operand1 / operand2); | ||||||||||||||||||||||
| }), | ||||||||||||||||||||||
| OPENED_PARENTHESIS("(", 3, (operand1, operand2) -> 0), | ||||||||||||||||||||||
| CLOSED_PARENTHESIS(")", 3, (operand1, operand2) -> 0); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| private static final Map<String, Operator> operators = | ||||||||||||||||||||||
| Collections.unmodifiableMap(Stream.of(values()) | ||||||||||||||||||||||
| .collect(Collectors.toMap(Operator::getSymbol, Function.identity()))); | ||||||||||||||||||||||
|
||||||||||||||||||||||
| private final String symbol; | ||||||||||||||||||||||
| private final int priority; | ||||||||||||||||||||||
| private final BiFunction<Integer, Integer, Integer> operation; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| Operator(String symbol, int priority, BiFunction<Integer, Integer, Integer> operation) { | ||||||||||||||||||||||
| this.symbol = symbol; | ||||||||||||||||||||||
| this.priority = priority; | ||||||||||||||||||||||
| this.operation = operation; | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| public static Integer calculate(String operator, Integer operand1, Integer operand2) { | ||||||||||||||||||||||
| return getSymbol(operator).operation.apply(operand1, operand2); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| public static Operator getSymbol(String operator) { | ||||||||||||||||||||||
| return Optional.ofNullable(operators.get(operator)) | ||||||||||||||||||||||
| .orElseThrow(() -> new IllegalArgumentException(ExceptionMessage.INVALID_SYMBOL)); | ||||||||||||||||||||||
|
||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
||||||||||||||||||||||
| public static Operator getSymbol(String operator) { | |
| return Optional.ofNullable(operators.get(operator)) | |
| .orElseThrow(() -> new IllegalArgumentException(ExceptionMessage.INVALID_SYMBOL)); | |
| } | |
| public static Operator getOperator(String input) { | |
| return Arrays.stream(Operator.values()) | |
| .filter(operator -> operator.symbol.equals(input)) | |
| .findFirst() | |
| .orElseThrow(() -> new IllegalArgumentException(ExceptionMessage.INVALID_SYMBOL)); | |
| } |
이런 방법은 어떠신가요?
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package co.programmers.domain; | ||
|
|
||
| import java.util.Collections; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
| import java.util.function.Function; | ||
| import java.util.stream.Collectors; | ||
| import java.util.stream.Stream; | ||
|
|
||
| public enum UserMenu { | ||
| INQUIRY("1"), | ||
| CALCULATE("2"), | ||
| TERMINATE("3"); | ||
|
|
||
| private static final Map<String, UserMenu> values = | ||
| Collections.unmodifiableMap(Stream.of(values()) | ||
| .collect(Collectors.toMap(UserMenu::getValue, Function.identity()))); | ||
|
||
| private final String value; | ||
|
|
||
| UserMenu(String value) { | ||
| this.value = value; | ||
| } | ||
|
|
||
| public static UserMenu get(String input) { | ||
| return Optional.ofNullable(values.get(input)).orElse(TERMINATE); | ||
| } | ||
|
||
|
|
||
| public String getValue() { | ||
| return value; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package co.programmers.exception; | ||
|
|
||
| public class ExceptionMessage { | ||
|
|
||
| public static final String DIVIDED_BY_ZERO = "0으로 나눌 수 없습니다."; | ||
| public static final String INVALID_SYMBOL = "잘못된 연산 기호입니다."; | ||
| public static final String INVALID_INPUT = "잘못된 입력입니다"; | ||
|
|
||
| private ExceptionMessage() { | ||
| } | ||
| } | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package co.programmers.view; | ||
|
|
||
| import co.programmers.exception.ExceptionMessage; | ||
| import co.programmers.domain.UserMenu; | ||
| import java.util.Arrays; | ||
| import java.util.Scanner; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| public class CalculatorInputView implements InputView { | ||
|
|
||
| private static final Scanner SCANNER = new Scanner(System.in); | ||
| private static final Set<String> USER_MENU = | ||
| Arrays.stream(UserMenu.values()) | ||
| .map(UserMenu::getValue) | ||
| .collect(Collectors.toSet()); | ||
|
||
|
|
||
| public CalculatorInputView() { | ||
| } | ||
|
||
|
|
||
| public String inputUserMenu() { | ||
| printMenuChoiceGuide(); | ||
| String userInput = SCANNER.next(); | ||
| SCANNER.nextLine(); | ||
| try { | ||
| validateUserMenuChoice(String.valueOf(userInput)); | ||
| } catch (IllegalArgumentException illegalArgumentException) { | ||
| System.out.println(illegalArgumentException.getMessage()); | ||
| return UserMenu.TERMINATE.getValue(); | ||
|
||
| } | ||
| return userInput; | ||
| } | ||
|
|
||
| public String inputExpression() { | ||
| printCalculationGuide(); | ||
| String expression = SCANNER.nextLine(); | ||
| return expression; | ||
| } | ||
|
|
||
| private void printCalculationGuide() { | ||
| System.out.println("1 + 2 * 3와 같은 형식으로 계산하고자 하는 식을 입력하세요."); | ||
| System.out.print("> "); | ||
| } | ||
|
|
||
| private void printMenuChoiceGuide() { | ||
| System.out.println("\n[다음 중 원하시는 항목을 숫자로 입력하세요]"); | ||
| System.out.println("1. 조회"); | ||
| System.out.println("2. 계산"); | ||
| System.out.println("3. 종료"); | ||
| System.out.print("> 선택 : "); | ||
| } | ||
|
||
|
|
||
| private void validateUserMenuChoice(String userInput) throws IllegalArgumentException { | ||
| if (!USER_MENU.contains(userInput)) { | ||
| throw new IllegalArgumentException(ExceptionMessage.INVALID_INPUT); | ||
| } | ||
| } | ||
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package co.programmers.view; | ||
|
|
||
| public class CalculatorOutputView implements OutputView { | ||
|
|
||
| public void print(String content) { | ||
| System.out.println(">> 결과 : " + content); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package co.programmers.view; | ||
|
|
||
| public interface InputView { | ||
|
|
||
| String inputUserMenu(); | ||
|
|
||
| String inputExpression(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package co.programmers.view; | ||
|
|
||
| public interface OutputView { | ||
|
|
||
| void print(String content); | ||
|
|
||
| } |
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.
👍