diff --git a/README.md b/README.md index bd90ef0247..69692403c0 100644 --- a/README.md +++ b/README.md @@ -1 +1,19 @@ -# java-calculator-precourse \ No newline at end of file +# java-calculator-precourse + +## 기능 목록 정의 + +### 기능 1. 커스텀 구분자 파싱 +- 규칙: 문자열이 "//"로 시작하면, 그 다음 한 글자를 커스텀 구분자로 설정 + +### 기능 2. 숫자 토큰 분리 +- 기본 구분자 "," ":" 허용 +- 커스텀 구분자가 있으면 기본 구분자와 함께 허용 +- ":"와 커스텀 구분자를 ","로 치환 후 ","로 split + +### 기능 3. 합산 +- 분리된 각 토큰을 정수로 변환해 모두 더함 +- 빈 항목이 나오면 예외 처리 + +### 기능 4. 검증 및 예외 +- 숫자 이외의 값, 0, 음수가 포함되면 IllegalArgumentException +- 예외는 그대로 종료 \ No newline at end of file diff --git a/src/main/java/calculator/Application.java b/src/main/java/calculator/Application.java index 573580fb40..b657cb3a94 100644 --- a/src/main/java/calculator/Application.java +++ b/src/main/java/calculator/Application.java @@ -1,7 +1,42 @@ package calculator; +import camp.nextstep.edu.missionutils.Console; + public class Application { public static void main(String[] args) { // TODO: 프로그램 구현 + System.out.println("덧셈할 문자열을 입력해 주세요."); + String input = Console.readLine(); + + // 개행 문자 처리 + input = input.replace("\\n", "\n"); + + // 빈 문자열이면 0 출력 + if (input.isEmpty()) { + System.out.println("결과 : 0"); + return; + } + + // 커스텀 구분자 파싱 + char customDelimiter = StrCalculator.setCustomDelimiter(input); + + // 본문 추출 + String body = input; + if (input.startsWith("//")) { + int nl = input.indexOf('\n'); + if (nl < 0) { + throw new IllegalArgumentException(); + } + body = input.substring(nl + 1); + } + + // 숫자 토큰 분리 + String[] tokens = StrCalculator.splitNumbers(body, customDelimiter); + + // 합산 & 검증 + int total = StrCalculator.sumNumbers(tokens); + + // 결과 출력 + System.out.println("결과 : " + total); } } diff --git a/src/main/java/calculator/StrCalculator.java b/src/main/java/calculator/StrCalculator.java new file mode 100644 index 0000000000..c5d519868c --- /dev/null +++ b/src/main/java/calculator/StrCalculator.java @@ -0,0 +1,79 @@ +package calculator; + +public class StrCalculator { + // 기능1 - 커스텀 구분자 파싱 + public static char setCustomDelimiter(String str) { + // 빈 문자열이면 종료 + if (str.isEmpty()) { + return 0; + } + // 커스텀 구분자 초기화 + char customDelimiter = 0; + + // "//" 다음 글자를 커스텀 구분자로 할당 + if (str.startsWith("//")) { + if (str.length() < 4) { + throw new IllegalArgumentException(); + } + customDelimiter = str.charAt(2); + } + return customDelimiter; + } + + // 기능2 - 숫자 토큰 분리 + public static String integrateDelimiters(String bodyStr, char customDelimiter) { + // 빈 문자열이면 종료 + if (bodyStr.isEmpty()) { + return bodyStr; + } + // 기본 구분자 ";"을 ","로 치환 + String integrated = bodyStr.replace(":", ","); + // 커스텀 구분자가 있으면 ","로 치환 + if (customDelimiter != 0) { + integrated = integrated.replace(String.valueOf(customDelimiter), ","); + } + return integrated; + } + + // ","으로 분리 + public static String[] splitNumbers(String bodyStr, char customDelimiter) { + // 구분자 통합 + String integrated = integrateDelimiters(bodyStr, customDelimiter); + // 빈 문자열이면 빈 배열 리턴 + if (integrated.isEmpty()) { + return new String[0]; + } + return integrated.split(",", -1); + } + + // 기능3 - 합산 + public static int sumNumbers(String[] tokens) { + // 빈 배열이면 0 + if (tokens.length == 0) { + return 0; + } + int total = 0; + for (int i = 0; i < tokens.length; i++) { + String token = tokens[i]; + // 빈 항목이면 예외 처리 + if (token.isEmpty()) { + throw new IllegalArgumentException(); + } + // 숫자 형식 검증 -> 숫자만 허용 + for (int j = 0; j < token.length(); j++) { + if (!Character.isDigit(token.charAt(j))) { + throw new IllegalArgumentException(); + } + } + // 정수형으로 변환 + int num = Integer.parseInt(token); + + // 0 또는 음수면 예외 처리 + if (num <= 0) { + throw new IllegalArgumentException(); + } + total += num; + } + return total; + } +}