Skip to content
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

[문자열 덧셈 계산기] 이준호 미션 제출합니다. #1912

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
27f9731
docs: Update README.md
Lanvizu Oct 18, 2024
18cd8c9
feat: 계산, 구분자 구별, 문자열 분할 하는 클래스 생성
Lanvizu Oct 18, 2024
431dc61
feat: view 생성
Lanvizu Oct 18, 2024
898a130
feat: Enum 타입 ErrorMessage 생성
Lanvizu Oct 21, 2024
d5b952b
feat: 에러 메세지 출력과 IllegalArgumentException 처리 기능 구현
Lanvizu Oct 21, 2024
d2d196a
feat: 구분자 형식 검사와 추출 구현
Lanvizu Oct 21, 2024
7d8afb4
test: DelimiterParser 클래스의 테스트 코드 구현
Lanvizu Oct 21, 2024
8acfe2d
Merge pull request #1 from Lanvizu/Lanvizu
Lanvizu Oct 21, 2024
ed288ee
feat: parse 메서드를 void로 수정
Lanvizu Oct 22, 2024
5dde8c1
test: parse 메서드를 void로 수정
Lanvizu Oct 22, 2024
943669a
feat: 초기 입력을 "\n"을 기준으로 나누기 구현
Lanvizu Oct 22, 2024
a75fc40
feat: 입력과 출력 클래스 따로 작성
Lanvizu Oct 22, 2024
0a7d9a6
feat: 설정된 구분자로 입력된 문장 나누기 구현
Lanvizu Oct 22, 2024
5f6de44
feat: 에러 메세지 추가 구현
Lanvizu Oct 22, 2024
8ccdfe4
feat: 출력 형태 메세지로 구현
Lanvizu Oct 22, 2024
bc7e726
feat: 입력받아 계산하는 Controller 구현
Lanvizu Oct 22, 2024
3ad961f
feat: 나눠진 문자열 입력받아 더하는 기능 구현
Lanvizu Oct 22, 2024
cdbc291
test: InputParser, StringSplitter 테스트 코드 구현
Lanvizu Oct 22, 2024
a9a5a5e
remove: 기존 계산 클래스 삭제
Lanvizu Oct 22, 2024
c792216
feat: main 메서드 정리 및 추가
Lanvizu Oct 22, 2024
2c0ad6d
Merge pull request #2 from Lanvizu/Lanvizu
Lanvizu Oct 22, 2024
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
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
# java-calculator-precourse
# java-calculator-precourse

## 구현할 기능 목록

1. 초기 구분자 설정
```
- Default Setting : (쉼표, 콜론)을 구분자로 설정
```

2. 사용자에게 문자열 입력 받음
```
- 입력받은 input이 비어있는 경우 예외 처리
- 입력받은 input이 "//"와 "\n" 으로 구분자를 설정하지 않은 경우 예외 처리
- 입력받은 input이 숫자 이외에 다른 문자가 입력된 경우 예외 처리
- 입력받은 input이 정해진 구분자 외의 문자로 구분되어 있는 경우 예외 처리
```

3. 커스텀 구분자의 유무 판단
```
- 커스텀 구분자 있는 경우
- 새로운 커스텀 구분자로 설정

- 커스텀 구분자 없는 경우
- 기존 구분자로 유지
```

4. 문자열을 구분자로 구분 하여 덧셈

5. 계산된 결과를 아래의 양식으로 출력한다
```
결과 : n
```
15 changes: 15 additions & 0 deletions src/main/java/calculator/Application.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
package calculator;

import calculator.domain.DelimiterParser;
import calculator.domain.InputParser;
import calculator.domain.StringSplitter;
import calculator.domain.SumCalculator;
import calculator.domain.controller.CalculatorController;
import calculator.view.InputView;

public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
InputParser inputParser = new InputParser();
DelimiterParser delimiterParser = new DelimiterParser();
StringSplitter stringSplitter = new StringSplitter();
SumCalculator sumCalculator = new SumCalculator();
CalculatorController calculatorController = new CalculatorController(inputParser, delimiterParser,
stringSplitter, sumCalculator);
String input = InputView.input();
calculatorController.run(input);
}
}
44 changes: 44 additions & 0 deletions src/main/java/calculator/domain/DelimiterParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package calculator.domain;

import static calculator.global.exception.ErrorMessage.EMPTY_CUSTOM_DELIMITER;
import static calculator.global.exception.ErrorMessage.INVALID_DELIMITER_START;

import calculator.global.exception.CalculatorException;

public class DelimiterParser {
private String delimiter;

public DelimiterParser() {
this.delimiter = ",|:";
}

// 새로운 구분자 설정
/*결과적으로 "//"로 시작하지 않는 경우 , "//"로 시작하더라도 구분자가 없는 경우*/
/*빈 값이 들어올 경우 디폴트 구분자로 유지*/
public void parse(String input) {
if (input == null || input.isEmpty()) {
return; // 빈 입력일 경우 기존 구분자
}
validateCustomDelimiterInput(input);
this.delimiter = extractCustomDelimiter(input);
}

// 입력된 구분자 형식 검사 ("//"로 시작 + "//" 제외 문자가 있는지 확인)
private void validateCustomDelimiterInput(String input) {
if (!input.startsWith("//")) {
throw CalculatorException.of(INVALID_DELIMITER_START);
}
if (input.length() == 2) {
throw CalculatorException.of(EMPTY_CUSTOM_DELIMITER);
}
}

// 입력에서 구분자 추출
private String extractCustomDelimiter(String input) {
return input.substring(2);
}

public String getDelimiter() {
return delimiter;
}
}
39 changes: 39 additions & 0 deletions src/main/java/calculator/domain/InputParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package calculator.domain;

import static calculator.global.exception.ErrorMessage.EMPTY_INPUT;

import calculator.global.exception.CalculatorException;

public class InputParser {
private String delimiterString;
private String inputString;

/*"\\n"을 기준으로 구분자 설정 입력과 문자열 입력을 나눠주는 메서드
* 빈 값이 들어오는 경우 예외 처리
* "\\n"이 포함되지 않는 경우 구분자 빈 값으로 저장*/
public void parse(String input) {
validateInput(input);
String[] parts = input.split("\\\\n", 2);
if (parts.length == 2) {
delimiterString = parts[0];
inputString = parts[1];
} else {
delimiterString = "";
inputString = input;
}
}

private void validateInput(String input) {
if (input == null || input.isEmpty()) {
throw CalculatorException.of(EMPTY_INPUT);
}
}

public String getDelimiterString() {
return delimiterString;
}

public String getInputString() {
return inputString;
}
}
76 changes: 76 additions & 0 deletions src/main/java/calculator/domain/StringSplitter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package calculator.domain;

import static calculator.global.exception.ErrorMessage.EMPTY_NUMBER_INPUT;
import static calculator.global.exception.ErrorMessage.INVALID_DELIMITER_INPUT;
import static calculator.global.exception.ErrorMessage.INVALID_STRING_END;
import static calculator.global.exception.ErrorMessage.INVALID_STRING_START;

import calculator.global.exception.CalculatorException;
import java.util.ArrayList;
import java.util.List;

public class StringSplitter {

/*구분자는 에러 없이 들어온다고 가정
* input 즉 /n 이후의 문자열에 대한 예외 처리 진행
* 이후 문자열을 정해진 구분자로 나눠주는 과정 진행*/
/*예외 처리
* 숫자로 시작하지 않는 경우
* 숫자로 끝나지 않는 경우
* 정해진 구분자가 아닌 문자가 들어간 경우*/

public String[] split(String input, String delimiter) {
validateInput(input, delimiter);
return input.split(delimiter);
}

// 빈 값, 숫자로 시작, 숫자로 끝나는 지 검증
private void validateInput(String input, String delimiter) {
if (input == null || input.isEmpty()) {
throw CalculatorException.of(EMPTY_NUMBER_INPUT);
}

List<String> parts = splitIntoParts(input);
if (!isValidStart(parts)) {
throw CalculatorException.of(INVALID_STRING_START);
}

if (!isValidEnd(parts)) {
throw CalculatorException.of(INVALID_STRING_END);
}

if (!containsOnlyValidCharacters(parts, delimiter)) {
throw CalculatorException.of(INVALID_DELIMITER_INPUT);
}
}

// 입력을 모든 문자로 쪼개는 메서드
private List<String> splitIntoParts(String input) {
List<String> parts = new ArrayList<>();
for (char c : input.toCharArray()) {
parts.add(String.valueOf(c));
}
return parts;
}

// 숫자로 시작하는지 체크
private boolean isValidStart(List<String> parts) {
return Character.isDigit(parts.getFirst().charAt(0));
}

// 숫자로 끝나는지 체크
private boolean isValidEnd(List<String> parts) {
return Character.isDigit(parts.getLast().charAt(0));
}

// 유효한 구분자만 포함되는지 체크
private boolean containsOnlyValidCharacters(List<String> parts, String delimiter) {
for (String part : parts) {
char ch = part.charAt(0);
if (!Character.isDigit(ch) && !delimiter.contains(part)) {
return false;
}
}
return true;
}
}
24 changes: 24 additions & 0 deletions src/main/java/calculator/domain/SumCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package calculator.domain;

import static calculator.global.exception.ErrorMessage.EMPTY_NUMBERS_INPUT;

import calculator.global.exception.CalculatorException;

public class SumCalculator {
public int calculateSum(String[] numbers) {
int sum = 0;
for (String number : numbers) {
validateNumbers(number);
sum += Integer.parseInt(number);
}
return sum;
}

// 빈 값 처리
private void validateNumbers(String number) {
if (number == null || number.isEmpty()) {
throw CalculatorException.of(EMPTY_NUMBERS_INPUT);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package calculator.domain.controller;

import calculator.domain.DelimiterParser;
import calculator.domain.InputParser;
import calculator.domain.StringSplitter;
import calculator.domain.SumCalculator;
import calculator.view.OutputView;


public class CalculatorController {

private final InputParser inputParser;
private final DelimiterParser delimiterParser;
private final StringSplitter stringSplitter;
private final SumCalculator sumCalculator;

public CalculatorController(InputParser inputParser, DelimiterParser delimiterParser,
StringSplitter stringSplitter, SumCalculator sumCalculator) {
this.inputParser = inputParser;
this.delimiterParser = delimiterParser;
this.stringSplitter = stringSplitter;
this.sumCalculator = sumCalculator;
}

public int processInput(String input) {

inputParser.parse(input);
String delimiterString = inputParser.getDelimiterString();
String inputString = inputParser.getInputString();

delimiterParser.parse(delimiterString);
String delimiter = delimiterParser.getDelimiter();

String[] numbers = stringSplitter.split(inputString, delimiter);

return sumCalculator.calculateSum(numbers);
}

public void run(String input) {
int totalSum = processInput(input);
OutputView.totalOutputLine(String.valueOf(totalSum));
}
}
11 changes: 11 additions & 0 deletions src/main/java/calculator/global/exception/CalculatorException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package calculator.global.exception;

public class CalculatorException extends IllegalArgumentException {
private CalculatorException(ErrorMessage errorMessage) {
super(errorMessage.getMessage());
}

public static CalculatorException of(ErrorMessage errorMessage) {
return new CalculatorException(errorMessage);
}
}
23 changes: 23 additions & 0 deletions src/main/java/calculator/global/exception/ErrorMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package calculator.global.exception;

public enum ErrorMessage {

EMPTY_INPUT("The input is empty."),
INVALID_DELIMITER_START("The input must start with '//' for custom delimiter."),
EMPTY_CUSTOM_DELIMITER("Custom delimiter cannot be empty after '//'."),
EMPTY_NUMBER_INPUT("The number cannot be empty."),
INVALID_STRING_START("The input must start with number"),
INVALID_STRING_END("The input must end with number"),
INVALID_DELIMITER_INPUT("The String currently has an incorrect delimiter."),
EMPTY_NUMBERS_INPUT("The numbers cannot be empty.");

private final String message;

ErrorMessage(String message) {
this.message = message;
}

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

import camp.nextstep.edu.missionutils.Console;

public class InputView {
private InputView() {
}

public static String input() {
return Console.readLine();
}
}
16 changes: 16 additions & 0 deletions src/main/java/calculator/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package calculator.view;

import calculator.view.constants.OutputType;

public class OutputView {
private OutputView() {
}

public static void commonOutputLine(String output) {
System.out.println(output);
}

public static void totalOutputLine(String output) {
System.out.println(OutputType.RESULT_TYPE.getMessage() + output);
}
}
15 changes: 15 additions & 0 deletions src/main/java/calculator/view/constants/OutputType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package calculator.view.constants;

public enum OutputType {
RESULT_TYPE("결과 : ");

private final String message;

OutputType(String message) {
this.message = message;
}

public String getMessage() {
return message;
}
}
Loading