계산기 ver.2

Yein Moon·2021년 6월 27일
0

개발일지

목록 보기
11/21
post-thumbnail

이전에 내가 짰던 엉망진창 말도 안되는 코드는 여기에 있다.

우선 기본적인 연산은 기본이고, 여러 연산을 연속적으로 할 수 있도록 구현하고 싶었다.
(내가 이전에 썼던 엉진망창 코드뿐 아니라 해설 시간에 시범으로 보여주셨던 코드도 firstNum에 완전 맨 처음 입력값만 기억할 수 있도록 한다는 문제점이 있었다. 예를 들어, 5 * 2의 계산을 = 연산한 뒤 -3을 하더라도 7 (=== 5*2-3)이 아니라, 2 (=== 5-3) 이 나오는 문제가 있었다.)

Pseudo Code

내가 가장 못하는 수도코드 작성부터 했다.

1. number가 입력될 때

#1. 맨 처음에 입력되는 경우, ( 초기값 0을 지우는 단계가 필요하므로 구분 )
즉, 연산자에 아무런 값이 없는 경우
(1) display 출력값이 0인 경우 button 값을 display에 출력한다.
(2) 그렇지 않다면 뒤에 이어 붙인다.

#2. 그렇지 않은 경우, ( === 맨처음 입력되는 경우가 아니라면 )
(1) previousKeyoperator라면 원래 display 출력값previousNum 에 넣고, 새로운 button값을 display에 출력한다.
(1-1) 그리고 previousKey값을 number로 바꾼다.
(2) previousKeyoperator가 아니라면, 뒤에 이어붙인다.

2. operator가 입력될 때

먼저 operator 변수에 button값을 넣는다. (여기서는 operatorForAdvanced)

#1. previousNum 값이 있는 경우 ( === 이전 숫자가 맨 처음 입력된 수가 아닐 경우 )
calculator 함수에 저장된 previousNum와 현재 display 출력값을 넣어 계산하여
display에 출력한다.( operatorcalculator와 같은 역할도 하는 부분 )
previousKeyoperator로 변경한다.

#2. 그렇지 않은 경우, (=== 가장 첫 연산자인 경우)
그냥 previousKeyoperator로 변경하기만 한다. (계산해 보여줄 값이 없으므로)

3. clear가 입력될 때

모두 초기값으로 돌려준다. 단, number가 입력될 때 operator이 없을 때를 기준으로 했는데 operator의 초기값이 undefined이므로 이 부분을 일치시켜준다.

4. calculator가 입력될 때

(1)calculate 함수를 계산해 display에 출력한다.
(2) previousNum는 초기화하여, 다음 연산자를 추가해 계산을 이어갈때도 두번 같은 계산이 이루어지지 않도록한다.


JS Code

수도코드를 기반으로 자바스크립트 코드를 작성하였다.

물론 그대로 작성해서 바로 되진 않았고, 엉뚱한 값이 나오기도 했다. 예를 들어, operator에서 operatorForAdvanced = buttonContent;가 조건에 상관없이 적용되어야할 구문이라 생각해 맨 위로 뺐었는데 그 결과 13*2+의 결과가 15가 나와버리는 문제가 생기기도 했다. (지금은 수정하여 if else문 뒤에 위치해있다.)

중간 중간 console.log를 넣어 여러 경우의 수에 내가 설계한대로 흘러가는지 확인할 수 있었다.

function calculate(n1, operator, n2) {
  let result = 0;
  if(operator === '+'){
    result = Number(n1) + Number(n2);
  } if(operator === '-'){
    result = Number(n1) - Number(n2);
  } if(operator === '*'){
    result = Number(n1) * Number(n2);
  } if(operator === '/'){
    result = Number(n1) / Number(n2);
  }
  return String(result);
}

const display = document.querySelector('.calculator__display--for-advanced'); // calculator__display 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
let firstNum, operatorForAdvanced, previousKey, previousNum;

buttons.addEventListener('click', function (event) {

  const target = event.target; // 클릭된 HTML 엘리먼트의 정보가 저장되어 있습니다.
  const action = target.classList[0]; // 클릭된 HTML 엘리먼트에 클레스 정보를 가져옵니다.
  const buttonContent = target.textContent; // 클릭된 HTML 엘리먼트의 텍스트 정보를 가져옵니다.

  if (target.matches('button')) {
    
    if (action === 'number') {
      if(operatorForAdvanced === undefined){ //가장 처음 입력하는 숫자인 경우,

        if(display.textContent === '0'){ //디스플레이 값이 0ㅇ이라면
          display.textContent = buttonContent; //새로운 버튼 값을 출력한다
        } else{ //0이 아니라면,
          display.textContent = display.textContent + buttonContent; //이어붙인다
        }

      } else{ //가장 처음 입력하는 숫자가 아닌 경우
        
        if(previousKey === 'operator'){ //이전값이 연산자라면
          previousNum = display.textContent; //원래 디스플레이값을 따로 저장하고
          display.textContent = buttonContent; //새로운 버튼 값을 출력한 뒤
          previousKey = 'number'; //'이전값은 숫자가 들어왔다'고 명시한다
        } else{ //이전값이 연산자가 아니라면
          display.textContent = display.textContent + buttonContent; //이어붙인다
        }  
      }
    }

    if (action === 'operator') {
      if(previousNum){ //앞서 저장된 숫자가 있을 경우, 즉 숫자값이 2개 이상인 경우
      display.textContent = calculate(previousNum, operatorForAdvanced, display.textContent); //계산한값을 출력하고
      previousKey = 'operator'; // '이전값은 연산자가 들어왔다'고 명시한다.

      } else{ //그렇지 않고 숫자값이 1개인 경우, 즉 처음 쓰이는 연산자라면
      previousKey ='operator'; //계산출력 없이 이전값 명시만 한다.
      }
      operatorForAdvanced = buttonContent; // 모든 과정을 거친후 operator에 버튼 값을 새로 저장한다.
    }
    
    if (action === 'clear') {
      previousNum = ''; 
      previousKey = '';
      operatorForAdvanced = undefined;
      display.textContent = '0';
    }

    if (action === 'calculate') {
      display.textContent = calculate(previousNum, operatorForAdvanced, display.textContent);
      previousNum = ''; //'=' 연산을 한 다음에도 계속 연산을 이어갈 수 있도록, previous값을 초기화한다.
    }
  }
});

아직 굳이 쓸모없는 부분이 있을 수 있고, 사칙연산 우선순위가 안지켜진다는 점(10+2*3의 결과로 16이 아니라 26가 나온다. 순서대로 계산하는 것에 그쳤기 때문에..)은 보완되지 못한 코드이다.

하지만 처음엔 손도 못댔던 문제에 어설프지만 나름 논리적으로 로직을 세우고 이를 구현했다는게 참 뿌듯했다 😀

profile
마스크 벗을 때쯤엔 주니어개발자 될끄니까

0개의 댓글