Evaluation of Expressions(2)

SangJun·2022년 10월 23일
0

자료구조

목록 보기
11/18
  • 문제 1. Infix notation 을 이용하여 표현된 수식을 파일(in1.txt)로 입력 받아, postfix notation 으로 변경하여
    화면에 출력하라. 단, 수식에서 모든 operand 는 1 자리 수의 양의 정수 (0~9)로 주어지고, operator 는 교재의
    알고리즘에서 제시된 ‘(’, ‘)’, ‘+’, ‘-’, ‘*’, ‘/’, ‘%’ 가 사용된다.
  • 문제 2. 파일 (in2.txt)로 주어진 postfix notation 의 수식을 evaluation 하는 코드를 작성하고, evaluation 결과를
    화면에 출력하라.

    가정: in1.txt, in2.txt 의 operand 및 operator 들은 공백 없이 한 개의 string 으로 주어지며, 이 string 의 길이는 100 이하 이다.

#include <iostream>
#include <fstream>
#include <string>
#define MAX_STACK_SIZE 100
#define MAX_EXPR_SIZE 100

using namespace std;
/**
* lparen은 stack에선 precedence 가장 낮고 expression에서 토큰으로 가져올 때 가장 높음
*/
typedef enum { lparen, rparen, plus, minus, times, divide, mod, eos, operand
} precedence;
precedence stack[MAX_STACK_SIZE]; //스택초기화
int intStack[MAX_STACK_SIZE];

/**precedence*/
static int isp[] = { 0, 19, 12, 12, 13, 13, 13, 0 };//in-stack_precedence
static int icp[] = { 20, 19, 12, 12, 13, 13, 13, 0 };//incoming_precedence

char expr[MAX_EXPR_SIZE]; char expr2[MAX_EXPR_SIZE]; // string expression
int top = -1;

void getInput() {
	fstream in("in1.txt"); int n = 0;
	while (!in.eof()) {
		in >> expr[n++];
	}
}
void getInput2() {
	fstream in("in2.txt"); int n = 0;
	while (!in.eof()) {
		in >> expr2[n++];
	}
}
precedence stackEmpty() {
	printf("스택이 비었습니다.\n");
	exit(EXIT_FAILURE);
}
precedence pop() {
	if (top == -1) {
		return stackEmpty();
	} 
	return stack[top--];
}
int popInt() {
	if (top == -1) {
		return stackEmpty();
	} 
	return intStack[top--];
}
/**
* precedence 자료형 stack에 push하는 함수
* stack[++top] = item;
* @param {precedence} item
*/
void push(precedence item) {
	stack[++top] = item;
}
void pushInt(int input) {
	intStack[++top] = input;
}
void print_token(precedence pop) {
	switch (pop) {
		case precedence::plus: printf("+"); break;
		case precedence::minus: printf("-"); break;
		case times: printf("*"); break;
		case divide: printf("/"); break;
		case mod: printf("%%"); break; //모듈러 연산자는 2개 써야 출력됨
	}	
}
precedence get_token(char *symbol, int* n, char expr[]){
	*symbol = expr[(*n)++]; //expr 은 스트링
	switch (*symbol) {
		case '(': return lparen;
		case ')': return rparen;
		case '+': return ::plus;
		case '-': return ::minus;
		case '*': return times;
		case '/': return divide;
		case '%': return mod;
		case '\0': return eos;
		default: return operand;
	}
}

void P1() { //infix notation to postfix notation 
	getInput();

	char symbol; //오퍼랜드, 오퍼레이터 등 의미가 있는 symbol
	precedence token; 
	int n = 0; //char[] 문자열 리스트 인덱스 이동에 사용
	stack[++top] = eos;

	for (token = get_token(&symbol, &n, expr); token != eos;
		token = get_token(&symbol, &n, expr))
	{ // 조건문 token != eos 가 거짓이면 ( token == eos 이면 ) for문 탈출
		if (token == operand) // token이 숫자면
			printf("%c", symbol); //바로출력
		else if (token == rparen) { //토큰이 ) 이면
			while (stack[top] != lparen) { // ( 나오기 전까지
				print_token(pop());
			}// stack pop하고 출력
			pop(); // ( 출력하지말고 del
		}
		else { //토큰이 operator이면 
			/*incoming precedence가 in stack precedence보다 크면 push,
				작으면 icp가 큰 값일때까지 pop하고 print*/
			while (isp[stack[top]] >= icp[token]) 
				print_token(pop());
			//그렇지 않으면 token push
			push(token);
		}
	}//eos 나올때까지 스택에 있는 operator 전부 pop하기
	while ((token = pop()) != eos) { 
		print_token(token);
	} 
	printf("\n");
}

void P2() { //postfix expression evaluation
	getInput2();
	precedence token; char symbol; int op1, op2; int n = 0;
	top = -1; //top 다시 초기화
	token = get_token(&symbol, &n, expr2); //우선 토큰 1개 받음
	while (token != eos) {
		if (token == operand)
			pushInt(symbol - '0');
		else {
			op2 = popInt(), op1 = popInt();
			switch (token) {
			case precedence::plus:
				pushInt(op1 + op2); break;
			case precedence::minus:
				pushInt(op1 - op2); break;
			case times:
				pushInt(op1 * op2); break;
			case divide:
				pushInt(op1 / op2); break;
			case mod:
				pushInt(op1 % op2);
			}
		}
		token = get_token(&symbol, &n, expr2);
	}
	printf("%d", popInt());
}

int main() {
	printf("문제 1: "); P1();
	printf("문제 2: "); P2();
	return 0;
}
profile
Let there be bit.

0개의 댓글