-
Notifications
You must be signed in to change notification settings - Fork 219
[문자열 덧셈 계산기] 김수현 미션 제출합니다. #212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
f650582
7313581
028b542
18e132f
af6c143
bf5f82c
cc0f6c2
bea9d28
697698f
39b6f20
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,31 @@ | ||
| # javascript-calculator-precourse | ||
| # javascript-calculator-precourse | ||
| # 1주차 - 문자열 덧셈 계산기 | ||
|
|
||
| ## ⚙️ 간단한 프로젝트 실행 흐름 | ||
| 1. 안내 문구를 출력한다. | ||
| 2. 사용자 입력을 수신한다. | ||
| 3. 입력 문자열을 parser로 넘겨 숫자 배열로 변환한다. | ||
| 4. 숫자 배열을 validator로 검증한다. | ||
| 5. 검증 통과 배열을 calculator로 합산한다. | ||
| 6. 합산 결과를 지정된 포맷으로 출력한다. | ||
| 7. 프로세스를 종료한다. | ||
|
|
||
|
|
||
| ## 🔧 구현할 기능 목록 | ||
|
|
||
| ### 1. parser (문자열 -> 숫자 배열 반환) | ||
| - [X] 기본 구분자(, :) 분리 및 숫자 배열 변환 | ||
| - [X] 커스텀 구분자 지정(문자열 앞부분의 "//", "\n") | ||
|
|
||
| ### 2. validator (숫자 배열 유효성 검사) | ||
| - [X] 숫자가 아닌 값이 포함된 경우 검증 | ||
| - [X] 양수가 아닌 값인 경우 검증 | ||
|
|
||
| ### 3. calculator (합산) | ||
| - [X] 빈 배열 합산 시 0 반환 | ||
| - [X] 그 외 숫자 배열 합산 | ||
|
|
||
| ### 4. App.js (전체 통합 테스트) | ||
| - [X] 모든 모듈 연동 | ||
| - [X] `App.run()` 실행 로직 완성 | ||
| - [X] `AplicationTest.js` 테스트 확인 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,23 @@ | ||
| import { MissionUtils } from "@woowacourse/mission-utils"; | ||
| import { InputParser } from "./InputParser.js"; | ||
| import { InputValidator } from "./InputValidator.js"; | ||
| import { Calculator } from "./Calculator.js"; | ||
|
|
||
| class App { | ||
| async run() {} | ||
| async run() { | ||
| try { | ||
| const input = await MissionUtils.Console.readLineAsync("덧셈할 문자열을 입력해 주세요.\n"); | ||
|
|
||
| const numbers = InputParser.parse(input); | ||
| InputValidator.validate(numbers); | ||
| const result = Calculator.sum(numbers); | ||
|
|
||
| MissionUtils.Console.print(`결과 : ${result}`) | ||
| } catch (error) { | ||
| MissionUtils.Console.print(error.message); | ||
| throw error; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| export default App; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| export class Calculator { | ||
| static sum(numbers) { | ||
| // 빈 배열인 경우 0 반환 | ||
| if (!numbers || numbers.length === 0){ | ||
| return 0; | ||
| } | ||
|
|
||
| // 그 외 숫자 배열인 경우 모든 숫자 합산 | ||
| const total = numbers.reduce((acc, cur) => acc + cur, 0); | ||
| return total; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| export class InputParser { | ||
| static parse(input) { | ||
| // 입력이 비어있거나 공백인 경우 | ||
| const raw = (input || "").trim(); | ||
| if (raw.length === 0) { | ||
| return []; | ||
| } | ||
|
|
||
| // 기본 구분자: 쉼표(,)와 콜론(:) | ||
| let delimiters = [",", ":"]; | ||
| let numbersPart = raw; | ||
|
|
||
| // 커스텀 구분자 | ||
| if (raw.startsWith("//")) { | ||
| const match = | ||
| raw.match(/^\/\/(.)\n(.*)/s) || // 실제 줄바꿈 | ||
| raw.match(/^\/\/(.)\\n(.*)/s); // 문자열 리터럴 "\n" | ||
| if (!match) { | ||
| throw new Error("[ERROR] 잘못된 커스텀 구분자 형식입니다."); | ||
| } | ||
| const [, custom, rest] = match; | ||
| delimiters = [",", ":", custom]; | ||
| numbersPart = rest; | ||
| } | ||
|
|
||
| const escaped = delimiters.map((d) => d.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 구분자에 특수문자가 포함될 수도 있다는 점을 고려해 정규식을 이렇게 안전하게 생성할 수도 있군요! 덕분에 escape 처리를 활용하는 방법을 배워갑니다 😊 |
||
| const regex = new RegExp(`(?:${escaped.join("|")})`, "g"); | ||
|
|
||
| // 숫자 배열로 변환 | ||
| return numbersPart | ||
| .split(regex) | ||
| .map((token) => token.trim()) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
입력 전체와 각 토큰에 대해 각각 |
||
| .filter((token) => token.length > 0) | ||
| .map((token) => Number(token)); // 숫자로 변환 | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| export class InputValidator { | ||
| static validate(numbers) { | ||
| // 숫자가 아닌 값이 포함된 경우 | ||
| const hasNonNumber = numbers.some((n) => | ||
| typeof n !== "number" || isNaN(n)); | ||
| if (hasNonNumber) { | ||
| throw new Error("[ERROR] 숫자가 아닌 값이 포함되어 있습니다."); | ||
| } | ||
|
|
||
| // 양수가 아닌 값(0 또는 음수) | ||
| const hasNegative = numbers.some((n) => n <= 0); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if (hasNegative) { | ||
| throw new Error("[ERROR] 양수가 아닌 값이 포함되어 있습니다."); | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
match를 활용해 커스텀 구분자를 이렇게 더 깔끔하게 파싱할 수 있었군요! 새로운 방법을 알아갑니다😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
커스텀 구분자를 한 글자만 인식하도록 되어 있는데, 혹시 여러 글자 구분자도 고려해볼 수 있을까요? 정규식을 확장한다면 어떤 식으로 바꿀 수 있을지 궁금합니다🧐