brunch

You can make anything
by writing

C.S.Lewis

[Flutter] #5 계산기 두번째 버전

들어가는 글: 지난 글에서는 계산기의 외관(UI)만 만들었습니다. 이제는 로직을 슬슬 붙여보시죠. 계산이 되어야 하자나요? 


1. 계산기는 단순하지 않다?  


계산기를 작성하는 방법은 다양합니다. 

가장 일반적으로는 다음과 같은 사항을 고려해야 합니다. 

1) 괄호 

2) 연산자 우선순위 

3) 사용자의 계속되는 입력 

4) 소수점 

5) C(clear)와 백스페이스(<-) 


예를 들어 (괄호)를 처리하려면 괄호 시작 부분부터 괄호의 끝 부분까지를 추출해서 별도로 계산을 해주어 합ㅣ다. 거기에 괄호는 중첩(nested) 될 수 있습니다. 그에 대한 처리도 해줘야 하죠. 


두번째 연산자는 우선순위가 있습니다. 잘 아시듯이 곱하기(*)와 나누기(/)는 서로 동등하고 

더하기(+)와 빼기(-) 보다는 높습니다. 연산자는 그것만이 아니죠 계산기에 잘 등장하지는 않지만 

모듈러(%) 연산자 같은 것도 있습니다. 그리고 괄호와 연산자 우선순위는 독립적이지 않죠. 괄호가 들어간 상태에서 연산자 우선순위를 함께 고려해야 합니다. 


세번째 사용자 입력은 한번에 들어오지 않습니다. 

예를 들어 "100 + 200 = " 입력이 들어오는 것은 실제로 

10 

100 

100 + 

100 + 2 

... 

이런식으로 들어옵니다. 그래서 언제 수식을 계산해줘야 하는지도 생각을 해야 합니다. 

단순히 생각하면 등호(=)가 들어올 때 해주면 되겠지만요. 


네번째는 소수점(.)입니다. 소수점이 들어오면 계산에서 생각해줘야 할 것이 더욱 늘어납니다. 

소수점은 한번만 입력되는 것이 아니고 여러번 입력될 수 있습니다. 

예를 들어 "1.. " 쩜쩜 두번 발생하면 어떻게 처리할 것인가? 

보통은 두번째 쩜이 입력되면 바로 튕겨주는 것이 좋지요. 안드로이드 앱이라고 하면 토스트(Toast)를 띄워주거나 다른 플랫폼이라면 사용자 입력창을 부르르 떨어주는 것도 좋겠네요. 


다섯번째는 조금 단순합니다. C를 누르면 수식을 모두 제거하면 되고 , 백스페이스를 한 글자씩 편집할 수 있습니다. 


생각보다 단순하지 않죠? 


2. 가장 단순한 계산 모델 


이제 소스 코드로 들어갑니다. 

(깃헙) https://github.com/yudong80/flutter-dev/blob/master/calculator/lib/calc_v2.dart 

(첫번째 버전) https://github.com/yudong80/flutter-dev/blob/master/calculator/lib/calc_v1.dart 


저는 위에서 말씀드린 거의 모든 것을 고려하지 않습니다 :-) 

그래서 구현이 단순합니다. 

1) 괄호 - 안씀 

2) 연산자 우선순위 - 상관없음 

- 오직 단일 연산자만 취급합니다. 예) 100 + 200 = ? 

3) 사용자 입력 - 단순하게 

- 숫자가 입력되고 , 사칙 연산자(+ - * /)가 입력되면 첫번째 피연산자(operand1) 을 인식합니다. 

- 그다음 등호(=)가 입력되면 두번째 피연산자(operand2)를 인식하고 

- 계산을 합니다. 

4) 소수점 - 안씀 

5) C 와 백스페이스 - Clear 만 지원 


로직을 살펴봅니다. 

(첫번째 버전)에서는 RaiseButton에 onPressed 이벤트를 연결시켰습니다. 

무언가 멋이 없죠? '7' 과 같은 것들이 두번 반복되고 있습니다. 

첫번째 버전의 버튼 배치


(두번째 버전)은 중복되는 부분을 CalcButton 클래스로 만들었습니다. 

맴버 변수로 _key를 가지고 있으며, 

사용자가 숫자를 누르면 onPressed 이벤트에 연결된 addNumbers() 함수가 호출됩니다.  


UI 부분도 중복없이 단순해집니다. 

훨씬 단순해진  버튼 배치


3. 로직 구현 코드 


addNumbers() 함수는 다음과 같습니다. 

사용자 입력이 key 변수로 들어오면 기본적으로 buffer에 쌓습니다. 

만약 'C'가 입력되면 버퍼를 초기화 합니다. (clear 구현) 

만약 사칙 연산자가 입력되면 첫번째 피연산자를 파싱합니다. double.parse 메서드를 호출합니다. 

만약 등호가 입력되면 두번째 피연산자를 같은 방법으로 파싱하고 계산을 시작합니다. 


계산 로직은 단순합니다. 

어렵지 않습니다. 이해되시죠? 사칙연산만 합니다. 


그런데??? 


그런데 아무리 등호(=)를 눌러도 화면이 변하지 않습니다. 

왜 그럴까요? 


그 이유는 (두번재 버전)도 여전히 StatelessWidget이기 때문입니다. 무상태 위젯은 생성된 후 한번만 표시되고 상태가 없기 때문에 화면을 갱신할 수 없습니다. 그러면 어떻게 해야 할까요? 


이 얘기는 계산기 (세번째 버전)으로 이어갑니다. 

다음 스토리를 기대해주세요. 


궁금하신 분들은 다음 깃헙에서 소스 코드를 찾아보셔도 됩니다. 이미 올려놓았어요. 

https://github.com/yudong80/flutter-dev


감사합니다. 

2019.5.18


글쓰는 제 모습입니다 :-)  #성수동 #할아버지공장


매거진의 이전글 [Flutter] #4 다트 언어에 대해 알아보자
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari