Schoolwork/자료구조와 C++프로그래밍

[C++] 7주차 과제5

FATKITTY 2020. 8. 5. 11:51
반응형

간단한 수식을 입력 받아서 계산을 해주는 계산기 프로그램을 작성한다.

반드시 Template 클래스와 스택을 사용하여 구현한다.

자세한 내용은 첨부한 pdf 파일을 참조하여 작성한다.

#문자열 입력으로 .이 입력될 때까지 재입력을 받도록 한다.

#헤더와 메인 파일은 분리하지 않고 한 개의 cpp파일을 제출한다. 

#입력값을 반복적으로 받을 수 있게 하고, .(마침표)를 입력하면 프로그램을 종료하도록 한다.

 

입력: 중위표기식 수식인 문자열

출력: 수식 계산 결과값, 입력 수식의 후위표기식

 

Code

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

template <class T>
class Stack {
public:
	Stack(int stackCapacity = 10);
	bool IsEmpty() const;
	T& Top() const;
	void Push(const T& item);
	void Pop();

private:
	T* stack;
	int top;
	int capacity;
};

template <class T>
Stack<T>::Stack(int stackCapacity) :capacity(stackCapacity)
{
	if (capacity < 1) throw "Stack capacity must be >= 0";
	stack = new T[capacity];
	top = -1;
}

template <class T>
void ChangeSize(T*& arr, const int oldsize, const int newsize)
{
	if (newsize < 0) throw "New length must be >= 0";

	T* temp = new T[newsize];
	int number = min(oldsize, newsize);
	copy(arr, arr + number, temp);
	delete[]arr;
	arr = temp;
}

template <class T>
inline bool Stack<T>::IsEmpty() const { return top == -1; }  // stack에 원소가 없다면 true, 있으면 false

template <class T>
inline T& Stack<T>::Top() const
{
	if (IsEmpty()) throw "Stack Empty";
	return stack[top];
}

template <class T>
void Stack<T>::Push(const T& x)
{
	if (top == capacity - 1)
	{
		ChangeSize(stack, capacity, 2 * capacity);
		capacity *= 2;
	}
	stack[++top] = x;
}

template <class T>
void Stack<T>::Pop()
{
	if (IsEmpty()) throw "Stack Empty. Cannot delete";
	stack[top--].~T();  // T에 대한 파괴자
}

int ICP(char t)  // In coming Priority
{
	// 계산기에 입력될 수식에 쓰일 연산자에 대해서만 우선순위 설정.
	// 음수부호- 는 입력조건이 0~9 이므로 고려하지 않는다.

	if (t == '(') return 0;
	else if (t == '*' || t == '/' || t == '%') return 2;
	else if (t == '+' || t == '-') return 3;
	else if (t == '#') return 8;
}

int ISP(char t)  // In Stack Priority
{
	if (t == '(') return 8;
	else if (t == '*' || t == '/' || t == '%') return 2;
	else if (t == '+' || t == '-') return 3;
}

string postfixResult;  // 후위표기식 변환결과를 따로 string으로 저장(global)

void Postfix(string exp)  // 중위표기식 -> 후위표기식 변환
{
	Stack<char> tokenStack;
	tokenStack.Push('#');

	for (int i = 0; (exp[i] != '#') && (i < exp.length()); i++)
	{
		char t = exp[i];

		if (isdigit(t))
		{
			cout << t << " ";  // 0~9 정수라면 그냥 그대로 출력
			postfixResult.push_back(t);
		}

		else if (t == ')') 
		{
			for (; tokenStack.Top() != '('; tokenStack.Pop()) {
				cout << tokenStack.Top() << " ";  // '(' 전 까지 출력
				postfixResult.push_back(tokenStack.Top());
			}
			tokenStack.Pop();  // unstack '('
		}

		else 
		{
			for (; ISP(tokenStack.Top()) <= ICP(t); tokenStack.Pop()) {
				// 앞에 들어올 연산자의 우선순위가 현재 연산자의 우선순위보다 작으면 출력 후 Pop
				cout << tokenStack.Top() << " ";
				postfixResult.push_back(tokenStack.Top());
			}
			tokenStack.Push(t);
		}
	}

	while (tokenStack.Top() != '#')  // #을 제외하고 출력
	{
		cout << tokenStack.Top() << " ";
		postfixResult.push_back(tokenStack.Top());
		tokenStack.Pop();
	}
	cout << endl;
}

float Eval(string postfix)
{
	// 앞에서부터 읽으며 피연산자는 스택에 쌓는다.
	// 연산자를 만나면 스택에서 피연산자 2개를 꺼내 연산을 수행하고 다시 스택에 쌓는다.
	// 끝날 때까지 계속 반복

	Stack<float> operandStack;  // 나눗셈 고려해서 float
	float result = 0;
	
	for (int i = 0; i < postfix.length(); i++)
	{
		char t = postfix[i];

		if (isdigit(t)) operandStack.Push(t - '0');  // char 데이터형을 int로 변환하기 위해 -'0'

		else
		{
			float op1 = operandStack.Top();
			operandStack.Pop();
			float op2 = operandStack.Top();
			operandStack.Pop();

			float temp = 0;  // 스택에 쌓을 연산결과를 담을 변수
			if (t == '+') temp = op2 + op1;
			if (t == '-') temp = op2 - op1;
			if (t == '*') temp = op2 * op1;
			if (t == '/') temp = op2 / op1;
			operandStack.Push(temp);
		}
	}

	result = operandStack.Top();
	operandStack.Pop();

	return result;
}

int main()
{
	cout << "> ";
	while (1) {
		string infix;  // 중위표기식 입력받기
		cin >> infix;
		if (infix[0] == '.') exit(0);  // . 입력시 종료
		Postfix(infix);
		cout << Eval(postfixResult) <<'\n' << endl;
		cout << "> ";
	}

	return 0;
}

실행결과

 

점수 10/10

 

 

  ❤와 댓글은 큰 힘이 됩니다. 감사합니다 :-)  

반응형

'Schoolwork > 자료구조와 C++프로그래밍' 카테고리의 다른 글

[C++] 11주차 과제7  (0) 2020.08.05
[C++] 9주차 과제6  (0) 2020.08.05
[C++] 5주차 과제4  (0) 2020.08.05
[C++] 3주차 과제3  (0) 2020.08.05
[C++] 2주차 과제2  (0) 2020.08.05