From e31714d3f4477577c7e62c0450933f85e57273c9 Mon Sep 17 00:00:00 2001 From: 1abme <124783124+1abme@users.noreply.github.com> Date: Mon, 20 Oct 2025 19:31:02 +0900 Subject: [PATCH 1/5] docs(readme): add feature list to README --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 13420b29..bc0e0906 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -# javascript-calculator-precourse \ No newline at end of file +# javascript-calculator-precourse + +## 기능 목록 + +- [ ] 빈 문자열 ("") 입력시 0을 반환 +- [ ] 쉼표(,) / 콜론(:)으로 숫자 구분 후 합 구하기 +- [ ] 커스텀 구분자는 "//<커스텀구분자>\n" 형식으로 지원 (ex. "//;\n1;2;3" -> 6) +- [ ] 결과 값의 형식은 '결과 : <합>' 으로 출력 +- [ ] 잘못된 입력 값은 "[ERROR]"로 시작하는 메시지와 Error 발생 후 종료 (process.exit() 미사용) From cec319817eebb0e14b5db4c287f5ea28d54bd157 Mon Sep 17 00:00:00 2001 From: 1abme <124783124+1abme@users.noreply.github.com> Date: Mon, 20 Oct 2025 20:44:55 +0900 Subject: [PATCH 2/5] feat(calculator): return 0 when input is empty string --- package-lock.json | 2 ++ src/App.js | 18 +++++++++++++++++- src/Calculator.js | 10 ++++++++++ src/index.js | 4 ---- 4 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 src/Calculator.js delete mode 100644 src/index.js diff --git a/package-lock.json b/package-lock.json index a1211435..bd7e7bd3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,6 +52,7 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -2969,6 +2970,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001663", "electron-to-chromium": "^1.5.28", diff --git a/src/App.js b/src/App.js index 091aa0a5..0e28ce28 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,21 @@ +import { Console } from "@woowacourse/mission-utils"; +import Calculator from "./Calculator.js"; + class App { - async run() {} + async run() { + try { + // 입력 받기 + const input = await Console.readLineAsync( + "덧셈할 문자열을 입력해 주세요." + ); + // 계산 처리 + const sum = Calculator.add(input); + // 결과 출력 + Console.print(`결과: ${sum}`); + } catch (err) { + console.print(err?.message ?? "[ERROR] 알 수 없는 오류가 발생했습니다."); + } + } } export default App; diff --git a/src/Calculator.js b/src/Calculator.js new file mode 100644 index 00000000..6dde7594 --- /dev/null +++ b/src/Calculator.js @@ -0,0 +1,10 @@ +const Calculator = { + add(input) { + // 빈 문자열 처리 + if (input === "") { + return 0; + } + }, +}; + +export default Calculator; diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 02a1d389..00000000 --- a/src/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import App from "./App.js"; - -const app = new App(); -await app.run(); From 65bf1ff248e91349cc6e27bf1802daed5a20cb50 Mon Sep 17 00:00:00 2001 From: 1abme <124783124+1abme@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:00:35 +0900 Subject: [PATCH 3/5] feat(calculator): sum numbers separated by '.' or ':' --- src/Calculator.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Calculator.js b/src/Calculator.js index 6dde7594..f31439f8 100644 --- a/src/Calculator.js +++ b/src/Calculator.js @@ -1,9 +1,14 @@ const Calculator = { add(input) { // 빈 문자열 처리 - if (input === "") { - return 0; - } + if (input === "") return 0; + + // 기본 구분자 처리 + const values = input.split(/[,:]/); + const numbers = values.map(Number); + + // 숫자 합산 + return numbers.reduce((acc, cur) => acc + cur, 0); }, }; From 63ad0b39777c1b2a2b3742f9ea532976a6b897fc Mon Sep 17 00:00:00 2001 From: 1abme <124783124+1abme@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:58:52 +0900 Subject: [PATCH 4/5] feat(calculator): add custom delimiter --- src/App.js | 8 ++++---- src/Calculator.js | 24 ++++++++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/App.js b/src/App.js index 0e28ce28..fb165871 100644 --- a/src/App.js +++ b/src/App.js @@ -5,15 +5,15 @@ class App { async run() { try { // 입력 받기 - const input = await Console.readLineAsync( + const INPUT = await Console.readLineAsync( "덧셈할 문자열을 입력해 주세요." ); // 계산 처리 - const sum = Calculator.add(input); + const RESULT = Calculator.add(INPUT); // 결과 출력 - Console.print(`결과: ${sum}`); + Console.print(`결과 : ${RESULT}`); } catch (err) { - console.print(err?.message ?? "[ERROR] 알 수 없는 오류가 발생했습니다."); + Console.print(err?.message ?? "[ERROR] 알 수 없는 오류가 발생했습니다."); } } } diff --git a/src/Calculator.js b/src/Calculator.js index f31439f8..6d7b63dc 100644 --- a/src/Calculator.js +++ b/src/Calculator.js @@ -3,12 +3,28 @@ const Calculator = { // 빈 문자열 처리 if (input === "") return 0; - // 기본 구분자 처리 - const values = input.split(/[,:]/); - const numbers = values.map(Number); + // 커스텀 구분자 처리 + const headerMatch = input.match(/^\/\/(.)(?:\\n|\n)/); + + // 숫자 영역 추출 (헤더 존재시 헤더 이후부터, 없으면 전체 사용) + const numbersPart = headerMatch + ? input.slice(headerMatch[0].length) + : input; + + // 구분자 정규식 (',', ':', 커스텀 구분자) + const delimiterRegex = new RegExp( + `[,:${ + headerMatch + ? headerMatch[1].replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&") + : "" + }]` + ); + + // 숫자 분리 (배열 변환) + const values = numbersPart.split(delimiterRegex); // 숫자 합산 - return numbers.reduce((acc, cur) => acc + cur, 0); + return values.reduce((acc, cur) => acc + Number(cur), 0); }, }; From 6247847d870e0547f9bee066d66bbc401b0dd1cd Mon Sep 17 00:00:00 2001 From: 1abme <124783124+1abme@users.noreply.github.com> Date: Mon, 20 Oct 2025 22:57:47 +0900 Subject: [PATCH 5/5] feat(validation): throw [ERROR] on invalid input --- src/App.js | 8 +++++++- src/Calculator.js | 12 ++++++++++++ src/constants/errors.js | 7 +++++++ src/utils/errors.js | 6 ++++++ 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/constants/errors.js create mode 100644 src/utils/errors.js diff --git a/src/App.js b/src/App.js index fb165871..abb943d7 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,6 @@ import { Console } from "@woowacourse/mission-utils"; import Calculator from "./Calculator.js"; +import { ERR } from "./constants/errors.js"; class App { async run() { @@ -13,7 +14,12 @@ class App { // 결과 출력 Console.print(`결과 : ${RESULT}`); } catch (err) { - Console.print(err?.message ?? "[ERROR] 알 수 없는 오류가 발생했습니다."); + const msg = + err && typeof err.message === "string" + ? err.message + : `[ERROR] ${ERR.UNKNOWN}`; + Console.print(msg); + throw err; } } } diff --git a/src/Calculator.js b/src/Calculator.js index 6d7b63dc..b1ab644a 100644 --- a/src/Calculator.js +++ b/src/Calculator.js @@ -1,3 +1,5 @@ +import { fail } from "./utils/errors.js"; + const Calculator = { add(input) { // 빈 문자열 처리 @@ -11,6 +13,9 @@ const Calculator = { ? input.slice(headerMatch[0].length) : input; + // 숫자 존재 여부 확인 + if (headerMatch && numbersPart === "") fail("EMPTY_NUMBER"); + // 구분자 정규식 (',', ':', 커스텀 구분자) const delimiterRegex = new RegExp( `[,:${ @@ -23,6 +28,13 @@ const Calculator = { // 숫자 분리 (배열 변환) const values = numbersPart.split(delimiterRegex); + // 유효성 검증 (빈 밸류, 비숫자, 음수) + for (const value of values) { + if (value === "") fail("EMPTY_VALUE"); + if (!/^-?\d+$/.test(value)) fail("NON_NUMBER"); + if (Number(value) < 0) fail("NEGATIVE_NUMBER"); + } + // 숫자 합산 return values.reduce((acc, cur) => acc + Number(cur), 0); }, diff --git a/src/constants/errors.js b/src/constants/errors.js new file mode 100644 index 00000000..fa8b7b2d --- /dev/null +++ b/src/constants/errors.js @@ -0,0 +1,7 @@ +export const ERR = { + EMPTY_NUMBER: "숫자 목록이 비어 있습니다.", + EMPTY_VALUE: "비어 있는 값이 포함되어 있습니다.", + NON_NUMBER: "숫자가 아닌 값이 포함되어 있습니다.", + NEGATIVE_NUMBER: "음수는 입력할 수 없습니다.", + UNKNOWN: "알 수 없는 오류가 발생했습니다.", +}; diff --git a/src/utils/errors.js b/src/utils/errors.js new file mode 100644 index 00000000..7fe2162b --- /dev/null +++ b/src/utils/errors.js @@ -0,0 +1,6 @@ +import { ERR } from "../constants/errors.js"; + +export const fail = (code) => { + const msg = ERR[code] || ERR.UNKNOWN; + throw new Error(`[ERROR] ${msg}`); +};