STEP 0 : Application.java
프로그램의 진입점 역할을 하며, View와 Controller를 생성하고 실행합니다.
package calculator;
public class Application {
public static void main(String[] args) {
CalculatorView view = new CalculatorView();
CalculatorController controller = new CalculatorController(view);
controller.processInput();
}
}
STEP 1-1 : DelimiterParser.java
- Model: DelimiterParser와 Calculator 클래스가 데이터 처리를 담당합니다.
- 구분자를 선별하여, 계산할 값만 추출하는 기능 (+값이 비어 있으면 곧바로, 0 출력.)
package calculator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DelimiterParser {
public static String[] parse(String input) {
// 입력값이 비어("\n") 있으면 숫자 0을 반환하는 메서드
if (input == null || input.trim().isEmpty()) {
return new String[] {"0"};
}
// 쉼표(,) 또는 콜론(:)을 구분자로 사용
String delimiter = ",|:";
input = input.replace("\\n", "\n");
String numbers = input;
if (input.startsWith("//")) {
// 사용자 정의 커스텀 구분자 추출 // "//"와 "\n" 사이에 위치
Matcher matcher = Pattern.compile("//(.*?)\n(.*)").matcher(input);
if (matcher.find()) {
if (matcher.group(1).isEmpty()) {
throw new IllegalArgumentException("Delimiter cannot be empty");
}
delimiter = Pattern.quote(matcher.group(1)) + "|,|:";
numbers = matcher.group(2);
}
}
// 구분자로 문자열을 분할하여 반환
return numbers.split(delimiter);
}
// public static void main(String[] args) {
// // 문자열을 코드 내부에 직접 넣어서 테스트
// String input = "//;\n1;2;3";
// String[] result = DelimiterParser.parse(input);
// int sum = 0;
// for (String number : result) {
// sum += Integer.parseInt(number); // 문자열을 숫자로 변환 후 더하기
// }
// System.out.println("결과: " + sum); // 결과 출력
// }
}
STEP 1-2 : Calculator.java
- Model: DelimiterParser와 Calculator 클래스가 데이터 처리를 담당합니다.
- 숫자 형태로 전환 후 합을 계산
package calculator;
import java.util.Arrays;
public class Calculator {
public static int calculateSum(String[] numbers) {
return Arrays.stream(numbers) // 배열을 스트림으로 변환하여, 원소들을 차례로 처리
.mapToInt(Calculator::parseNumber) // parseNumber 메서드를 사용하여 문자열을 숫자로 변환
.sum();
}
private static int parseNumber(String number) {
try {
// 공백 제거
String trimmedNumber = number.trim();
// 공백인 경우 0으로 처리
if (trimmedNumber.isEmpty()) {
return 0;
}
int parsedNumber = Integer.parseInt(trimmedNumber);
if (parsedNumber < 0) {
throw new IllegalArgumentException("Negative numbers are not allowed: " + number);
}
return parsedNumber;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("잘못된 값을 입력하셨습니다. 애플리케이션은 종료됩니다. 입력값:" + number, e);
}
}
}
STEP 2 : CalculatorView.java
View: CalculatorView 클래스가 사용자로부터 값을 입력받는다.
package calculator;
import camp.nextstep.edu.missionutils.Console;
public class CalculatorView {
public String getInput() {
System.out.println("덧셈할 문자열을 입력해 주세요.");
String input = Console.readLine();
// 입력값이 null이거나 빈 문자열인 경우 0으로 처리
if (input == null || input.isEmpty()) {
return "0"; // 빈 문자열을 0으로 처리
}
return input;
}
public void displayResult(int result) {
System.out.println("결과 : " + result);
}
public void displayError(String message) {
throw new IllegalArgumentException(message);
}
}
STEP 3 : CalculatorController.java
- Controller: CalculatorController 클래스가 Model과 View를 연결하고 전체 로직을 제어한다.
package calculator;
public class CalculatorController {
private CalculatorView view; // 컨트롤러에서 사용할 View 객체
public CalculatorController(CalculatorView view) {
this.view = view; // Application에서 전달받은 View를 저장
}
public void processInput() {
// View를 사용해, 입력을 받는다
String input = view.getInput();
try {
String[] numbers = DelimiterParser.parse(input);
int result = Calculator.calculateSum(numbers);
// View를 사용해, 결과를 출력
view.displayResult(result);
} catch (IllegalArgumentException e) {
view.displayError(e.getMessage());
}
}
}
+) DelimiterParserTest.java
//package calculator;
//
//import static org.assertj.core.api.Assertions.assertThat;
//import static org.assertj.core.api.Assertions.assertThatThrownBy;
//
//import org.junit.jupiter.api.Test;
//
//class DelimiterParserTest {
//
// @Test
// void parse_숫자_하나() {
// String input = "1";
// String[] result = DelimiterParser.parse(input); // 클래스 이름을 사용하여 호출
// assertThat(result).containsExactly("1");
// }
//
// @Test
// void parse_기본_구분자() {
// String input = "1,2:3";
// String[] result = DelimiterParser.parse(input);
// assertThat(result).containsExactly("1", "2", "3");
// }
//
// @Test
// void parse_커스텀_구분자() {
// String input = "//;\n1;2;3";
// String[] result = DelimiterParser.parse(input);
// assertThat(result).containsExactly("1", "2", "3");
// }
//
// @Test
// void parse_기본_구분자_커스텀_구분자() {
// String input = "//;\n1;2,3:4";
// String[] result = DelimiterParser.parse(input);
// assertThat(result).containsExactly("1", "2", "3", "4");
// }
//
// @Test
// void parse_커스텀_구분자_다양() {
// String input = "//$%\n1,2,3";
// String[] result = DelimiterParser.parse(input);
// assertThat(result).containsExactly("1", "2", "3");
// }
//
// @Test
// void invalidCustomDelimiter_커스텀_구분자_없음() {
// String input = "//\n1,2:3";
// assertThatThrownBy(() -> DelimiterParser.parse(input))
// .isInstanceOf(IllegalArgumentException.class);
// }
//}
기능 요구 사항
입력한 문자열에서 숫자를 추출하여 더하는 계산기를 구현한다.
- 쉼표(,) 또는 콜론(:)을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환한다.
- 예: "" => 0, "1,2" => 3, "1,2,3" => 6, "1,2:3" => 6
- 앞의 기본 구분자(쉼표, 콜론) 외에 커스텀 구분자를 지정할 수 있다. 커스텀 구분자는 문자열 앞부분의 "//"와 "\n" 사이에 위치하는 문자를 커스텀 구분자로 사용한다.
- 예를 들어 "//;\n1;2;3"과 같이 값을 입력할 경우 커스텀 구분자는 세미콜론(;)이며, 결과 값은 6이 반환되어야 한다.
- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.
입출력 요구 사항
입력
- 구분자와 양수로 구성된 문자열
출력
- 덧셈 결과
결과 : 6
실행 결과 예시
덧셈할 문자열을 입력해 주세요.
1,2:3
결과 : 6
프로그래밍 요구 사항
- JDK 21 버전에서 실행 가능해야 한다.
- 프로그램 실행의 시작점은 Application의 main()이다.
- build.gradle 파일은 변경할 수 없으며, 제공된 라이브러리 이외의 외부 라이브러리는 사용하지 않는다.
- 프로그램 종료 시 System.exit()를 호출하지 않는다.
- 프로그래밍 요구 사항에서 달리 명시하지 않는 한 파일, 패키지 등의 이름을 바꾸거나 이동하지 않는다.
- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
- 기본적으로 Java Style Guide를 원칙으로 한다.
라이브러리
- camp.nextstep.edu.missionutils에서 제공하는 Console API를 사용하여 구현해야 한다.
- 사용자가 입력하는 값은 camp.nextstep.edu.missionutils.Console의 readLine()을 활용한다.
'[JAVA] 개발' 카테고리의 다른 글
[우아한테크코스] 2주차 자동차 경주 (1) | 2024.10.29 |
---|---|
[JAVA] JDK 21 설치, 환경 변수 설정 (1) | 2024.10.17 |
Java Software Solution Ch7_PP3 (0) | 2024.05.01 |
Java Software Solution Ch7_PP2 (0) | 2024.05.01 |
Java Software Soution Ch7_PP8 (0) | 2024.05.01 |