Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
# javascript-calculator-precourse
## ➕ 문자열 덧셈 계산기 체크리스트

### 기능 구현

- [ ] 빈 문자열 입력 시 `0` 반환
- [ ] 기본 구분자 (`,` `:`) 로 숫자 분리
- [ ] 커스텀 구분자 `"//<구분자>\n"` 형식 지원
- [ ] 잘못된 입력 시 `[ERROR]` 메시지 출력
- [ ] 양수만 허용
- [ ] `Console.readLineAsync`, `Console.print` 사용
- [ ] 출력 형식: `결과 : <합계>`

### 예외 처리

- [ ] 음수 입력 시 에러 발생
- [ ] 숫자 아닌 값 입력 시 에러 발생
- [ ] 잘못된 포맷 입력 시 에러 발생
- [ ] 연속 구분자 처리 정책 반영
17 changes: 16 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import { readInput, printResult, printError } from "./io/InputHandler.js";
import { calculateSum } from "./calculator/Calculator.js";

class App {
async run() {}
async run() {
try {
const input = await readInput();
const sum = calculateSum(input);
printResult(sum);
} catch (err) {
const message = `[ERROR] ${(
err?.message ?? "알 수 없는 오류가 발생했습니다."
).replace(/^\[ERROR\]\s*/, "")}`;
printError(message);
throw new Error(message);
}
}
}

export default App;
14 changes: 14 additions & 0 deletions src/calculator/Calculator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Parser from "./Parser.js";
import { validateTokens } from "./Validator.js";

export function calculateSum(input) {
if (input == null) throw new Error("입력이 필요합니다.");
if (input === "") return 0;

const normalized = String(input).replace(/\\n/g, "\n");

const tokens = Parser.parse(normalized);
validateTokens(tokens);

return tokens.reduce((sum, t) => sum + Number(t), 0);
}
25 changes: 25 additions & 0 deletions src/calculator/Parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Parser {
static escapeForRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}

static parse(input) {
if (!input) return [];

let delimiters = [",", ":"];
let expression = input;

const m = input.match(/^\/\/(.)\n/);
if (m) {
delimiters.push(m[1]);
expression = input.slice(m[0].length);
}

const pattern = new RegExp(
`[${Parser.escapeForRegExp(delimiters.join(""))}]`
);
return expression.split(pattern);
}
}

export default Parser;
17 changes: 17 additions & 0 deletions src/calculator/Validator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export function validateTokens(tokens) {
if (!Array.isArray(tokens)) {
throw new Error("유효하지 않은 입력입니다.");
}

for (const t of tokens) {
if (t === "") throw new Error("유효하지 않은 구분자 사용입니다.");

if (!/^-?\d+$/.test(t)) throw new Error("숫자만 입력할 수 있습니다.");

const n = Number(t);

if (n < 0) throw new Error("음수는 허용되지 않습니다.");

if (n === 0) throw new Error("양수만 입력할 수 있습니다.");
}
}
13 changes: 13 additions & 0 deletions src/io/InputHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Console } from "@woowacourse/mission-utils";

export async function readInput() {
Console.print("덧셈할 문자열을 입력해 주세요.");
const input = await Console.readLineAsync("");
return input;
}
export function printResult(result) {
Console.print(`결과 : ${result}`);
}
export function printError(message) {
Console.print(message);
}