diff --git a/README.md b/README.md index 13420b29..4f6e2cc0 100644 --- a/README.md +++ b/README.md @@ -1 +1,25 @@ -# javascript-calculator-precourse \ No newline at end of file +# javascript-calculator-precourse + +## 구현할 기능 목록 + +### > 초기 질문 출력 및 문자열 입력 받은 후, 예시 결과 출력 + +- `@woowacourse/mission-utils` 패키지의 `Console` 객체를 사용하여 `초기 질문 출력`, `문자열 입력` 기능을 수행하도록 한다. +- 마찬가지로 예시 결과 출력도 `Console` 객체를 사용하여 요구사항대로 구현하고자 한다. +- 예시 결과까지 출력하는 이유는 프로그램의 전체적인 뼈대를 잡고, 핵심 기능에 집중하기 위함이다. + +### > 핵심 기능 구현 - divider를 기준으로 값 계산 및 예시 결과를 실제 결과로 바꿈 + +- 프로그램의 전체적인 flow는 잡았으니, 핵심 기능(계산)에 집중한다. +- 입력받은 string을 해석하는 기능을 구현한다. +- divider를 기준으로 number 값을 구분하여 가져올 때마다 변수에 직접 합산하는 로직을 구현한다. + +### > 핵심 기능 구현 - new divider를 수용하도록 로직 추가 + +- 요구사항에 따라 divider가 변수화 돼야 한다. 따라서 하드코딩된 divider를 변수화 하여, //\n 와 같은 형태로, "//"와 "\n" 사이에 존재하는 string을 divider로 사용한다. + +### > 사용자 친화적인 마무리 작업 + +- 입력 받은 데이터가 parse 후 number가 아닌 경우 계산하지 않고, 경고 메시지를 출력한다. +- 만일 "1:2,,3:4"과 같은 입력이 들어왔을 경우 빈 number 데이터가 생기게 되는데, 빈 number 데이터를 0으로 처리함 으로써 편의성을 높일 수 있다고 생각하여 그렇게 처리하도록 한다. +- new divider를 받을 때, 공백이 있을 경우 공백을 삭제하고 divider를 지정할까? 라고 생각 했지만, 1-space divider, 2-space divider ... n-space divider도 수행되어야 함으로, 이 기능을 구현하지 않는다. diff --git a/src/App.js b/src/App.js old mode 100644 new mode 100755 index 091aa0a5..10cc6743 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,110 @@ +import { Console } from "@woowacourse/mission-utils"; + +const DEFAULT_DIVIDER = [",", ":"]; +const NEW_DIVIDER_SYNTAX_CHAR = ["/", "\\", "n"]; + class App { - async run() {} + _isNaN(value, onNotANumber) { + const isNotANumber = isNaN(value); + isNotANumber && onNotANumber && onNotANumber(); + return isNotANumber; + } + + async run() { + // 사용자의 입력을 받는다. + let validInputFlag = false; + let userInput = ""; + while (!validInputFlag) { + userInput = await Console.readLineAsync( + "덧셈할 문자열을 입력해 주세요. \n" + ); + if (userInput.trim() !== "") validInputFlag = true; + } + const charsOfUserInput = Array.from(userInput); + + // 공통 예외처리 함수 + const exceptionFunc = () => { + console.error( + "[ERROR] 입력한 값이 숫자가 아닙니다. 프로그램을 종료합니다." + ); + process.exit(); + }; + + // 계산을 수행한다. + let calcResult = 0; + let numberMemory = ""; // string으로 누적하도록 수정 + + // 2가 되면 `isNewDivider` flag 변수를 활성화 시킨다. + let newDividerActivateCount = 0; + let newDividerDeActivateFlag = 0; // 이전 char가 '\'여야 함을 분기하기 위해 사용하는 변수다. + charsOfUserInput.forEach((char, i) => { + let newDivider = ""; + let isNewDivider = false; + const isDivider = isNewDivider + ? isNewDivider === char + : DEFAULT_DIVIDER.includes(char); + const isDigit = /[0-9]/.test(char); + + console.log("isNewDivider :>> ", isNewDivider); + // 새로운 divider를 저장 + if (isNewDivider) { + newDivider += char; + console.log(`store new divider ${newDivider}`); + return; + } + + // new divider를 위한 char별 분기 로직 + if (NEW_DIVIDER_SYNTAX_CHAR[1] === char) { + newDividerDeActivateFlag = true; + return; + } + if (newDividerDeActivateFlag && NEW_DIVIDER_SYNTAX_CHAR[2] === char) { + isNewDivider = false; + return; + } + if (NEW_DIVIDER_SYNTAX_CHAR[0] === char) { + if (++newDividerActivateCount == 2) { + isNewDivider = true; + } + return; + } + if (isNewDivider) { + newDivider += char; + return; + } + + console.log(`isDivider on ${char} :>> `, isDivider); + // divider일 경우 메모리 숫자 파싱 후 결과에 합산 + if (isDivider) { + const _num = parseInt(numberMemory || "0", 10); + this._isNaN(_num, exceptionFunc); // 예외처리 + calcResult += _num; + numberMemory = ""; + return; + } + + // 예외 처리 + if (!isDigit) { + // isNaN 검사를 통해 예외처리 함수 실행하도록 함 + this._isNaN(Number(char), exceptionFunc); + return; + } + + // 숫자일 경우 메모리에 누적 + numberMemory += char; + + // 마지막 문자이면 메모리 파싱하여 합산 + if (i === charsOfUserInput.length - 1) { + const _num = parseInt(numberMemory, 10); + this._isNaN(_num, exceptionFunc); // 예외처리 + calcResult += _num; + numberMemory = ""; + } + }); + + // 계산된 결과를 출력한다. (현재는 예시 결과 출력) + Console.print(`결과 : ${calcResult}`); + } } export default App;