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() 미사용) 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..abb943d7 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,27 @@ +import { Console } from "@woowacourse/mission-utils"; +import Calculator from "./Calculator.js"; +import { ERR } from "./constants/errors.js"; + class App { - async run() {} + async run() { + try { + // 입력 받기 + const INPUT = await Console.readLineAsync( + "덧셈할 문자열을 입력해 주세요." + ); + // 계산 처리 + const RESULT = Calculator.add(INPUT); + // 결과 출력 + Console.print(`결과 : ${RESULT}`); + } catch (err) { + const msg = + err && typeof err.message === "string" + ? err.message + : `[ERROR] ${ERR.UNKNOWN}`; + Console.print(msg); + throw err; + } + } } export default App; diff --git a/src/Calculator.js b/src/Calculator.js new file mode 100644 index 00000000..b1ab644a --- /dev/null +++ b/src/Calculator.js @@ -0,0 +1,43 @@ +import { fail } from "./utils/errors.js"; + +const Calculator = { + add(input) { + // 빈 문자열 처리 + if (input === "") return 0; + + // 커스텀 구분자 처리 + const headerMatch = input.match(/^\/\/(.)(?:\\n|\n)/); + + // 숫자 영역 추출 (헤더 존재시 헤더 이후부터, 없으면 전체 사용) + const numbersPart = headerMatch + ? input.slice(headerMatch[0].length) + : input; + + // 숫자 존재 여부 확인 + if (headerMatch && numbersPart === "") fail("EMPTY_NUMBER"); + + // 구분자 정규식 (',', ':', 커스텀 구분자) + const delimiterRegex = new RegExp( + `[,:${ + headerMatch + ? headerMatch[1].replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&") + : "" + }]` + ); + + // 숫자 분리 (배열 변환) + 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); + }, +}; + +export default Calculator; 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/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(); 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}`); +};