Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ group = 'camp.nextstep'
version = '1.0.0'
sourceCompatibility = '1.8'


repositories {
mavenCentral()
}

dependencies {
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30'
implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
testImplementation "org.junit.jupiter:junit-jupiter:5.7.2"
testImplementation "org.assertj:assertj-core:3.19.0"
}
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/study/StringCalculatorApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package study;

import study.model.CalculatorScanner;
import study.model.StringCalculator;

public class StringCalculatorApplication {
public static void main(String[] args){
CalculatorScanner scanner = new CalculatorScanner();
String value = scanner.getInput();

StringCalculator calculator = new StringCalculator();
System.out.println("계산 결과 : " + calculator.calculate(value));
}
}
14 changes: 14 additions & 0 deletions src/main/java/study/exception/DivisionZeroException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package study.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import study.exception.enumclass.ErrorCode;

public class DivisionZeroException extends RuntimeException{
private static final Logger logger = LoggerFactory.getLogger(DivisionZeroException.class);

public DivisionZeroException(ErrorCode errorCode) {
super(errorCode.getMessage());
logger.error("DivisionZeroException 발생: {}", errorCode.getMessage());
}
}
15 changes: 15 additions & 0 deletions src/main/java/study/exception/InvalidFormatException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package study.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import study.exception.enumclass.ErrorCode;


public class InvalidFormatException extends RuntimeException{
private static final Logger logger = LoggerFactory.getLogger(InvalidFormatException.class);

public InvalidFormatException(ErrorCode errorCode) {
super(errorCode.getMessage());
logger.error("InvalidFormatException 발생: {}", errorCode.getMessage());
}
}
14 changes: 14 additions & 0 deletions src/main/java/study/exception/InvalidInputException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package study.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import study.exception.enumclass.ErrorCode;

public class InvalidInputException extends RuntimeException{
private static final Logger logger = LoggerFactory.getLogger(InvalidInputException.class);

public InvalidInputException(ErrorCode errorCode) {
super(errorCode.getMessage());
logger.error("InvalidInputException 발생: {}", errorCode.getMessage());
}
}
27 changes: 27 additions & 0 deletions src/main/java/study/exception/enumclass/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package study.exception.enumclass;

public enum ErrorCode {

NON_NUMERIC_INPUT(1, "숫자가 아닌 값을 입력했습니다."),
DIVISION_ZERO(2, "0으로 나눌 수 없습니다."),
INVALID_FORMAT(3, "잘못된 형식입니다. 정확한 수식을 입력해주세요."),
EMPTY_INPUT(4, "공백은 입력할 수 없습니다.");



private final int id;
private final String message;

ErrorCode(int id, String message) {
this.id = id;
this.message = message;
}

public int getId() {
return id;
}

public String getMessage() {
return message;
}
}
28 changes: 28 additions & 0 deletions src/main/java/study/model/CalculatorScanner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package study.model;

import study.exception.InvalidInputException;
import study.exception.enumclass.ErrorCode;

import java.util.NoSuchElementException;
import java.util.Scanner;

public class CalculatorScanner {
private final Scanner scanner;

public CalculatorScanner(){
this.scanner = new Scanner(System.in);
}

public String getInput(){
System.out.println("수식을 입력해주세요: ");
String input;

try {
input = scanner.nextLine();
} catch (NoSuchElementException ex){
throw new InvalidInputException(ErrorCode.EMPTY_INPUT);
}

return input;
}
}
41 changes: 41 additions & 0 deletions src/main/java/study/model/Operator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package study.model;

import study.exception.DivisionZeroException;
import study.exception.InvalidFormatException;
import study.exception.enumclass.ErrorCode;

public class Operator {
public int execute(String operators, int nowValue, int nextValue){
switch (operators){
case "+":
return add(nowValue, nextValue);
case "-":
return minus(nowValue, nextValue);
case "*":
return multiply(nowValue, nextValue);
case "/":
return divide(nowValue, nextValue);
}
throw new InvalidFormatException(ErrorCode.INVALID_FORMAT);
}

public int add(int num1, int num2){
return num1 + num2;
}

public int minus(int num1, int num2){
return num1 - num2;
}

public int multiply(int num1, int num2){
return num1 * num2;
}

public int divide(int num1, int num2){
if (num2 == 0){
throw new DivisionZeroException(ErrorCode.DIVISION_ZERO);
}

return num1 / num2;
}
}
43 changes: 43 additions & 0 deletions src/main/java/study/model/StringCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package study.model;

import study.exception.InvalidFormatException;
import study.exception.InvalidInputException;
import study.exception.enumclass.ErrorCode;


public class StringCalculator {
public int calculate(String value){
String[] values = value.split(" ");

int total = parseInteger(values[0]);

for (int i=1; i<values.length; i+=2){
String operators = values[i];
int nextValue = getNextValue(values, i+1);

Operator operator = new Operator();
total = operator.execute(operators, total, nextValue);
}

return total;

}

public int getNextValue(String[] values, int index){
if (index >= values.length){
throw new InvalidFormatException(ErrorCode.INVALID_FORMAT);
}
return parseInteger(values[index]);
}

public int parseInteger(String value){
try{
return Integer.parseInt(value);
} catch (NumberFormatException e){
throw new InvalidInputException(ErrorCode.NON_NUMERIC_INPUT);
}
}



}
53 changes: 53 additions & 0 deletions src/test/java/study/CalculatorScannerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package study;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import study.exception.InvalidInputException;
import study.exception.enumclass.ErrorCode;
import study.model.CalculatorScanner;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class CalculatorScannerTest {

@Test
@DisplayName("사용자 입력 성공")
void getInput_success(){
// given
String input = "2 + 2";
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);

CalculatorScanner scanner = new CalculatorScanner();

// when
String result = scanner.getInput();

// then
assertEquals(result, input);
}


@Test
@DisplayName("사용자 입력 시 공백 입력한 경우")
void getInputEmpty_invalidInputException(){
// given
String input = "";
InputStream in = new ByteArrayInputStream(input.getBytes());
System.setIn(in);

CalculatorScanner scanner = new CalculatorScanner();

// when
InvalidInputException fail = assertThrows(InvalidInputException.class,
() -> scanner.getInput());

// then
assertEquals(fail.getMessage(), ErrorCode.EMPTY_INPUT.getMessage());
}

}
118 changes: 118 additions & 0 deletions src/test/java/study/OperatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package study;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import study.exception.DivisionZeroException;
import study.exception.InvalidFormatException;
import study.exception.enumclass.ErrorCode;
import study.model.Operator;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class OperatorTest {
private Operator operator;

@BeforeEach
void setUp(){
operator = new Operator();
}

@Test
@DisplayName("연산자 구분 함수 성공")
void executeOperator_success(){
// given
String operators = "+";
int nowValue = 1;
int nextValue = 2;

// when
int result = operator.execute(operators, nowValue, nextValue);

// then
assertEquals(result, 1+2);
}

@Test
@DisplayName("switch 문에 존재하지 않는 연산자 제공한 경우")
void executeOperator_InvalidFormatException(){
// given
String operators = " ";
int nowValue = 3;
int nextValue = 2;

// when
InvalidFormatException fail = assertThrows(InvalidFormatException.class, () -> operator.execute(operators, nowValue, nextValue));

// then
assertEquals(fail.getMessage(), ErrorCode.INVALID_FORMAT.getMessage());
}

@Test
@DisplayName("더하기 함수 성공")
void add_success(){
// given
int num1 = 1, num2 = 2;

// when
int result = operator.add(num1, num2);

// then
assertEquals(result, 3);
}

@Test
@DisplayName("빼기 함수 성공")
void minus_success(){
// given
int num1 = 1, num2 = 2;

// when
int result = operator.minus(num1, num2);

// then
assertEquals(result, -1);
}

@Test
@DisplayName("곱하기 함수 성공")
void multiply_success(){
// given
int num1 = 5, num2 = 2;

// when
int result = operator.multiply(num1, num2);

// then
assertEquals(result, 10);
}

@Test
@DisplayName("나누기 함수 성공")
void divide_success(){
// given
int num1 = 5, num2 = 2;

// when
int result = operator.divide(num1, num2);

// then
assertEquals(result, 2);
}

@Test
@DisplayName("0으로 나눈 경우")
void divideZero_divisionZeroException(){
// given
int num1 = 5, num2 = 0;

// when
DivisionZeroException fail = assertThrows(DivisionZeroException.class,
() -> operator.divide(num1, num2));

// then
assertEquals(fail.getMessage(), ErrorCode.DIVISION_ZERO.getMessage());
}

}
Loading