diff --git a/README.md b/README.md index bd90ef0247..b46e83970b 100644 --- a/README.md +++ b/README.md @@ -1 +1,34 @@ -# java-calculator-precourse \ No newline at end of file +# java-calculator-precourse + +## 1) 목표 +인풋 문자열로부터 기준에 따라 양의 정수를 추출하여 합을 반환하는 프로그램 작성 + +## 2) 입출력 정의 +- **Input**: `camp.nextstep.edu.missionutils.Console.readLine()` 을 이용. +- **Output**: `결과 : ` 형태로 출력. +- **예외로 인한 종료**: `IllegalArgumentException` 을 Throw (`System.exit()` 호출 **금지** ). + +## 3) 추출 규칙 +1. **기본 구분자(delimiter)**: comma (`,`) and colon (`:`). + - 예시: `"" -> 0`, `"1,2" -> 3`, `"1,2,3" -> 6`, `"1,2:3" -> 6` +2. **커스텀 구분자**: `"//<커스텀구분자>\n<숫자>"` + - 예시: `"//;\n1;2;3" -> 6` (커스텀 구분자는 `;`) +3. **유효 토큰**: 모든 숫자는 **양수** ( > 0 ). +4. **공백**: 일단 trimming 은 고려 X + +## 4) 예외 규칙 (`IllegalArgumentException`) +- 음수 등장 시 ( ex: `-1,2`). +- 기본 구분자, 커스텀 구분자를 제외한 입력값 등장 시 +- 커스텀 구분 등장 시, 문법을 지키지 않을 시 + + +## 5) Output Format +- 성공 시: `결과 : ` +- 실패 시: throw `IllegalArgumentException` + +## 6) 그 외 Constraints +- **JDK 21**. +- **Entry point**: `Application.main(String[] args)`. +- 제공된 **Console API** 사용: `Console.readLine()`. +- **수정 X** `build.gradle`. 외부 라이브러리 X, 제공된 라이브러리만 사용 +- **사용 X** `System.exit()`. diff --git a/src/main/java/calculator/Application.java b/src/main/java/calculator/Application.java index 573580fb40..16967f34da 100644 --- a/src/main/java/calculator/Application.java +++ b/src/main/java/calculator/Application.java @@ -1,7 +1,18 @@ 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(); + + StringCalculator calculator = new StringCalculator(); + int result = calculator.add(input); + + System.out.println("결과 : " + result); } -} + + } + diff --git a/src/main/java/calculator/StringCalculator.java b/src/main/java/calculator/StringCalculator.java new file mode 100644 index 0000000000..440341dc94 --- /dev/null +++ b/src/main/java/calculator/StringCalculator.java @@ -0,0 +1,58 @@ +package calculator; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StringCalculator { + + private static final Pattern DEFAULT_DELIMS = Pattern.compile("[,:]"); + private static final Pattern CUSTOM_HEADER = Pattern.compile("^//(.)\\n(.*)$", Pattern.DOTALL); + + public int add(String input) { + // Null 문자열은 0 반환 + if (input == null || input.trim().isEmpty()) { + return 0; + } + + Matcher m = CUSTOM_HEADER.matcher(input); + if (m.matches()) { + String delim = m.group(1); + String body = m.group(2); + if (body == null || body.trim().isEmpty()) { + return 0; + } + String regex = Pattern.quote(delim); + String[] tokens = body.split(regex, -1); + return sumTokens(tokens); + } + + // '//'로 시작하나 커스텀 구분자 문법이 잘못 됐을 때 + if (input.startsWith("//")) { + throw new IllegalArgumentException("커스텀 구분자 형식이 잘못됐습니다."); + } + + String[] tokens = DEFAULT_DELIMS.split(input, -1); + return sumTokens(tokens); + } + + private int sumTokens(String[] tokens) { + if (tokens.length == 0) { + throw new IllegalArgumentException("tokens가 비어있음"); + } + int sum = 0; + for (String token : tokens) { + if (token.isEmpty()) { + throw new IllegalArgumentException("token이 비어있음"); + } + if (!token.chars().allMatch(Character::isDigit)) { + throw new IllegalArgumentException("숫자가 아닌 token: " + token); + } + int value = Integer.parseInt(token); + if (value <= 0) { + throw new IllegalArgumentException("양수가 아닌 number: " + token); + } + sum += value; + } + return sum; + } +}