응애맘마조

231101 강의 본문

공부/UE강의

231101 강의

TH.Wert 2023. 11. 1. 16:02

오늘은 언리얼이 아니고 중위 표기법, 후위 표기법을 이용한 스택 계산기를 만들었습니다.

#pragma once
#include <iostream>
using namespace std;
#include <Windows.h>
#include "stdafx.h"
#include <vector>

#define NULLNUM INT_MAX

struct NODE
{
	float num;
	char  c;
};
//비어있는 노드
NODE tempNode;
//연산자와 피연산자를 담을 벡터
vector<NODE> vectorNode;

//후위표기법용 벡터
vector<NODE> clac;
//연산자 벡터
vector<NODE> Char;

void GetPostFix();

int main()
{
	FILE* fp = NULL;
	//파일 열기
	fopen_s(&fp, "calc.txt", "r");

	//받아올 문자
	char temp;
	//방금 저장한값이 2자리 이상의 수인지 비교
	float num = NULLNUM;
	//소수점 계산에 쓰일 변수 3개
	float num2 = NULLNUM;
	int num3 = NULLNUM;

	int Count = NULLNUM;

	while (1)
	{
		if (feof(fp))break;

		fscanf_s(fp, "%c", &temp);
		switch (temp)
		{
			//연산자 및 괄호일 경우
		case '(':case ')':case '+':case '*':case '/':
			//방금전에 읽었던 값이 숫자였는지
			if (num != NULLNUM)
			{
				//벡터에 숫자로 추가한다
				tempNode.num = num;
				tempNode.c = NULL;
				vectorNode.emplace_back(tempNode);
				
				num2 = NULLNUM;
				num = NULLNUM;
			}
			//숫자를 저장하고 난뒤 연산자를 추가
			tempNode.num = NULLNUM;
			tempNode.c = temp;
			vectorNode.emplace_back(tempNode);

			break;
			//숫자 일때

			//음수인지 연산자 - 인지 구분
		case '-':
			if (vectorNode.empty() || vectorNode.back().c == '('
				|| vectorNode.back().c == '+' || vectorNode.back().c == '/'
				|| vectorNode.back().c == '-' || vectorNode.back().c == '*')
			{
				//뒤에 오는 숫자를 실수형으로 전부다 읽기
				fscanf_s(fp, "%f", &num2);
				tempNode.num = num2 * -1.0f;
				tempNode.c = NULL;
				vectorNode.emplace_back(tempNode);
				num2 = NULLNUM;
				num = NULLNUM;
			}
			//연산자인 - 경우
			else
			{
				tempNode.num = NULLNUM;
				tempNode.c = temp;
				vectorNode.emplace_back(tempNode);
			}

			break;
			//소수점일 경우
		case '.':
			//뒤에 오는 숫자를 실수형으로 전부다 읽기
			fscanf_s(fp, "%f", &num2);
			num3 = 1;
			Count = 0;
			//읽어온 num2 자리수 확인
			while(num3 > num2)
			{
				num3 *= 10;
				Count++;
			}
			//소수점 이하 값 만들어주기
			for (int i = 0; i < Count + 1; i++)
			{
				num2 *= 0.1f;
			}
			num += num2;

			tempNode.num = num;
			tempNode.c = NULL;
			vectorNode.emplace_back(tempNode);
			num2 = NULLNUM;
			num = NULLNUM;
			Count = NULLNUM;

			break;

		default:
			//앞에 숫자가 있었다면
			if (num != NULLNUM)
			{
				num = num * 10.0f + atoi(&temp);
			}
			//앞에 숫자가 아니였다면
			else
			{
				num= atoi(&temp);
			}
			break;
		}
	}

	fclose(fp);
	//마지막에 한번 더 들어간 빼기
	vectorNode.pop_back();

	cout << "중위 표기법" << endl;
	for (int i = 0; i < vectorNode.size(); i++)
	{
		if (vectorNode[i].num != NULLNUM)
		{
			cout << vectorNode[i].num << endl;
		}
		else
		{
			cout << vectorNode[i].c << endl;
		}
	}
	GetPostFix();

	cout << "후위 표기법" << endl;
	for (int i = 0; i < clac.size(); i++)
	{
		if (clac[i].num != NULLNUM)
		{
			cout << clac[i].num << endl;
		}
			
		else
		{
			cout << clac[i].c << endl;
		}	
	}
	
	//원래 있던 노드 비우기
	vectorNode.clear();
	vectorNode.shrink_to_fit();

	//역순으로 vectorNode 에 값채우기
	while (1)
	{
		if (clac.size() < 1)break;
		vectorNode.emplace_back(clac.back());
		clac.pop_back();
	}
	
	while (1)
	{
		if (vectorNode.size() < 1)break;

		//숫자인경우
		if (vectorNode.back().num != NULLNUM)
		{
			clac.emplace_back(vectorNode.back());
			vectorNode.pop_back();
		}
		//연산자 일때
		else
		{
			float f1, f2;
			f1 = clac.back().num;
			clac.pop_back();
			f2 = clac.back().num;
			clac.pop_back();
			switch (vectorNode.back().c)
			{
			case '+':
				tempNode.num = f1 + f2;
				tempNode.c = NULL;
				clac.emplace_back(tempNode);
				break;
			case '*':
				tempNode.num = f1 * f2;
				tempNode.c = NULL;
				clac.emplace_back(tempNode);
				break;
			case '/':
				tempNode.num = f2/ f1;
				tempNode.c = NULL;
				clac.emplace_back(tempNode);
				break;
			case '-':
				tempNode.num = f2 - f1;
				tempNode.c = NULL;
				clac.emplace_back(tempNode);
				break;
			}

			//마지막에 하나 빼준다.
			vectorNode.pop_back();
		}
	}

	cout << "답은" << clac.back().num << endl;

	int a;
	cin >> a;

	return 0;
}

void GetPostFix()
{
	for (int i = 0; i < vectorNode.size(); i++)
	{
		//숫자인 경우 후위 표기법용 벡터에 넣는다(숫자는 그냥출력한다)
		if (vectorNode[i].num != NULLNUM)
		{
			clac.emplace_back(vectorNode[i]);
		}

		//연산자인경우
		else
		{
			switch (vectorNode[i].c)
			{
				//여는 괄호를 만나면 조건없이 연산자 벡터에 넣기
			case  '(':Char.emplace_back(vectorNode[i]);
				break;
				//닫는 괄호를 만나면 연산자벡터에 ( 만날때까지 꺼내서 출력
			case')':
				while (Char.back().c!= '(')
				{
					//연산자벡터 있던 마지막놈을 출력문끝에 넣기
					clac.emplace_back(Char.back());
					Char.pop_back();
				}
				Char.pop_back();//마지막인 ( 를 빼준다.

				break;
			case '+': case '-':
				//여는괄호나 연산자 벡터가 비어있지 않을때까지
				while (Char.size() != 0 && Char.back().c != '(')
				{
					//연산자벡터 있던 마지막놈을 출력문끝에 넣기
					clac.emplace_back(Char.back());
					Char.pop_back();
				}
				//비교해서 꺼낸다음 자신은 연산자 벡터에 추가
				Char.emplace_back(vectorNode[i]);
				break;
			case '*': case '/':
				//여는괄호나 연산자 벡터가 비어있지 않고
				//자신과 우선순위 동일한 연산자 까지
				while (Char.size() != 0 && Char.back().c != '('
					&&(Char.back().c != '*'|| Char.back().c != '/'))
				{
					//연산자벡터 있던 마지막놈을 출력문끝에 넣기
					clac.emplace_back(Char.back());
					Char.pop_back();
				}
				//비교해서 꺼낸다음 자신은 연산자 벡터에 추가
				Char.emplace_back(vectorNode[i]);
				break;
			}
		}
	}
    
	while (1)
	{
		//연산자벡터가 빌때까지
		if (Char.size() < 1)break;
		//출력문에 전부 끝에 붙여주기
		clac.emplace_back(Char.back());
		Char.pop_back();
	}
}

숫자와 연산자를 따로 읽는 방법입니다. 연산자를 배열에 추가하고 빼서 사용하는 방식입니다.

 

읽어주셔서 감사합니다.

'공부 > UE강의' 카테고리의 다른 글

231103 강의  (0) 2023.11.04
231102 강의  (0) 2023.11.04
231031 강의  (0) 2023.10.31
231030 강의  (0) 2023.10.30
231027 강의  (0) 2023.10.27
Comments