연재 완료/자료구조 이론

10. 스택&큐 활용 -b. 수식계산기

라이피 (Lypi) 2018. 11. 8. 23:32
반응형

수식 계산기

  # 중위 표현식으로 적혀진 수식을 후위 표현식으로 변환하여 계산한 결과를 리턴한다.

  # 수식은 문자열로 입력 받는다.

  # 수식은 괄호가 없고 한자리 수의 사칙연산임을 가정했다.

  # 즉, +-보다 */를 먼저 계산하도록 한 것 뿐이다.

  # 원래는 괄호까지 처리할 수 있어야 하는데 자꾸 문제가 생겨서 나중에 시간나면 처리하기로 했다.

  # 스택과 큐는 연결 리스트 기반을 사용했다.

  # run함수에 수식을 전달하면 계산 결과를 리턴받을 수 있다.


스택&큐 구현은 생략 (앞의 포스트 참조)


계산기 구현

 #pragma once
#include "Queue_list.h"
#include "stack_list.h"

#include <iostream>
#include <tchar.h>

#if defined(UNICODE) || defined(_UNICODE)
#define tcout std::wcout
#define tcin std::wcin

#else
#define tcout std::cout
#define tcin std::cin

#endif

class calculator
{
	TCHAR infixStr[256];
	QueueList<TCHAR> PostfixQueue;
	StackList<TCHAR> OperatorStack;
	StackList<int>  OperandStack;

public:
	void InputFormula(const TCHAR* str);
	void InToPost();
	int Prioty(TCHAR op1);
	int Calculate();

	int run(const TCHAR* str);

public:
	calculator();
	virtual ~calculator();
};

calculator::calculator()
{

}

void calculator::InputFormula(const TCHAR* str)
{
	_tcscpy_s(infixStr, str);
}

int calculator::Prioty(TCHAR op)
{
	if (op == '+' || op == '-') { return 1; }
	if (op == '*' || op == '/') { return 2; }
}

void calculator::InToPost()
{
	int iStrlen = _tcslen(infixStr) + 1;

	for (int i = 0; i < iStrlen; i++) {
		if (isdigit(infixStr[i])) { PostfixQueue.Add(infixStr[i]); }
		else {
			if (OperatorStack.Count() == 0) { OperatorStack.Push(infixStr[i]); }
			else {
				if (Prioty(OperatorStack.Peek()) < Prioty(infixStr[i])) { OperatorStack.Push(infixStr[i]); }
				else {
					PostfixQueue.Add(OperatorStack.Pop());
					i--;
					continue;
				}
			}
		}
	}
}

int calculator::Calculate()
{
	do {
		TCHAR buf = PostfixQueue.Peek();
		if (isdigit(buf)) {
			OperandStack.Push(buf-48);
			PostfixQueue.Remove();
		}
		else {
			PostfixQueue.Remove();

			int i1, i2;
			i2 = OperandStack.Pop();
			i1 = OperandStack.Pop();

			if (buf == '+') { OperandStack.Push(i1 + i2); }
			else if (buf == '-') { OperandStack.Push(i1 - i2); }
			else if (buf == '*') { OperandStack.Push(i1 * i2); }
			else if (buf == '/') { OperandStack.Push(i1 / i2); }
		}
	} while (PostfixQueue.Count() != 0);

	return OperandStack.Peek();
}

int calculator::run(const TCHAR* str) 
{
	InputFormula(str);
	InToPost();
	return Calculate();
}


calculator::~calculator()
{

}


반응형