단순한 방정식(예 : (a+b) * (c*d) / f) 계산하여 결과값을 출력하는 코드
infix형태의 식을 입력하면 그 식을 postfix형태로 변환
변환된 식을 차례대로 계산하여 최종결과 출력
실행예제
코드
//
// main.cpp
// Postfix
//
// Created by eungchan Kang on 2020/03/25.
/*
단순한 식(예 : (a+b) * (c*d) / 8) 계산하여 결과값을 출력하는 코드
infix형태의 식을 입력하면 그 식을 postfix형태로 변환
변환된 식을 차례대로 계산하여 최종결과 출력
*/
#include <iostream>
#include <stack>
using namespace std;
//방정식에 들어있는 연산자들
// 소괄호는 만일 방정식에 괄호가 있을 시, 처리해주기 위한 것
char operators[] = {'+','-','*','/','%','('};
// Node 클래스 포인터 생성
// 생성한 포인터로 스택이라는 생성자 만들기
typedef class Node * NodePtr;
typedef NodePtr Stack;
// 연산자는 char type, 비연산자는 integer type
typedef char Operator;
typedef int operand;
string String;
// key는 비연산자, value는 연산자
class Node{
private:
operand key;
Operator value;
NodePtr next;
public:
Node(){}
friend Stack CreateStack();
friend bool IsEmpty(Stack S);
friend bool IsFull(Stack S);
template<typename T> // 비연산자(int)와 연산자(char) 타입이 다르므로 임의로 처리하기 위해 T로 지정
friend T Top(Stack S, bool bit);
template <typename T>
friend void Push(Stack S, T X, bool bit);
template <typename T>
friend T Pop(Stack S, bool bit);
friend void DeleteStack(Stack S);
};
// 새로운 스택을 만들어 모든 attributes을 초기화 하고 리턴
Stack CreateStack(){
Stack S = new Node();
if(S == NULL)
{
perror("Out of Space\\n");
exit(1);
}
S->key = 0;
S->value = '\\0';
S->next = NULL;
return S;
}
bool IsEmpty(Stack S){
return S->next == NULL;
}
// 스택의 Top을 리턴하는 함수
// 연산자(char)와 비연산사(int)를 모두 처리해야 하므로 template 사용
// bit가 true이면 비연산자 출력, false이면 연산자 출력
template <typename T>
T Top(Stack S, bool bit){
if(!IsEmpty(S))
{
if(bit == true)
return S->next->key;
else
return S->next->value;
}
else{
perror("Stack is Empty\\n");
return 0;
}
}
// bit가 true이면 비연산자 모드로 실행(char type으로 실행)
// bit가 false이면 연산자 모드로 실행(int type으로 실행)
template <typename T>
void Push(Stack S, T X, bool bit){
Stack pushed_node = new Node();
if(bit)
pushed_node->key = X;
else
pushed_node->value = X;
pushed_node->next = S->next;
S->next = pushed_node;
}
template <typename T>
T Pop(Stack S, bool bit){
T picked_element;
if(!IsEmpty(S)){
Stack picked_node = S->next;
S->next = picked_node->next;
if (bit == true)
picked_element = picked_node->key;
else
picked_element = picked_node->value;
free(picked_node);
return picked_element;
}
else
{
perror("Stack is empty\\n");
return 0;
}
}
// 스택 전체를 삭제하는 함수
void DeleteStack(Stack S){
Stack Del = S->next;
Stack temp;
while(Del != NULL){
temp = Del->next;
free(Del);
Del = temp;
}
free(S);
}
// 해당 문자가 연산자인지 아닌지를 체크하는 함수
bool check_operator(char input_str){
for (int i = 0; i < strlen(operators); i++)
{
if(input_str == operators[i])
return true;
}
return false;
}
// 방정식 계산을 수행하는 함수
operand Perform_op(int a, int b, char op){
switch(op){
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
if(b == 0){
perror("\\nzero cannot be denominator\\n");
exit(1);
}
return a/b;
case '%':
if(b == 0){
perror("\\nzero cannot be denominator\\n");
exit(1);
}
return a%b;
default:
break;
}
return 0;
}
// Postfix형태로 변화된 문자열을 차례로 받아서
// 숫자(비연산자)가 나오면 스택에 넣고 연산자가 나오면
// 스택에 있는 숫자 두 개를 뽑아서 계산하고
// 결과를 다시 스택에 푸시하는 방법으로 진행
void Postfix(Stack S, char input_str){
if(input_str > '0' && input_str <= '9'){ //숫자가 나오는 경우
operand X = input_str - '0';
Push(S, X, true);
}
else if(check_operator(input_str) == true) //연산자가 나오는 경우
{
operand a = Pop<int>(S,true);
operand b = Pop<int>(S, true);
operand X = Perform_op(b, a, input_str);
Push(S,X,true);
}
else
{
perror("Invalid input\\n");
}
}
void Postfix_play(Stack stack, string input_str);
//infix 형태로 입력되는 문자열 방정식을 Postfix형태로 변환하여 Postfix함수로 리턴
void Infix(Stack S, char input_str){
//string String;
if(check_operator(input_str) == true) //입력되는 문자가 연산자가 맞으면 스택에 푸시 '('까지 포함하여
Push(S, input_str, false);
else if(input_str == ')') //스캔 과정에 ')'를 만나면 '('를 찾을 때까지 pop진행 (a+b), 이렇게 이미 '('이 반드시 스택에 존재.
{
char tmp;
while((tmp = Pop<char>(S, false)) != '(') //pop하는 연산자들은 순서대로 스트링에 넣기
String += tmp; // 나중에 postfix함수에 파라미터로 넘기는 string
}
else if(input_str == '#') // '#'을 만나면 마지막이라는 것이고, 그럼 스택에 남아 있는 연산자를 모두 pop하여 string 뒤에 붙이기
{
char tmp;
while(!IsEmpty(S)){
tmp = Pop<char>(S, false);
String += tmp;
}
String += '#';
cout<<String<<endl;;
Postfix_play(S, String);
}
else if(input_str >= '1' && input_str <= '9') // 숫자를 만나면 바로 string뒤에 붙이기
String += input_str;
else
perror("Invalid input\\n");
}
//문자열을 받아서 infix함수에 한 문자씩 넘기면서 끝날 때까지 변환 수행
void Infix_play(Stack stack, string input_str)
{
for (int i = 0; i < input_str.size(); i++){
Infix(stack, input_str.at(i));
}
}
// Infix에서 넘긴 문자열을 하나의 문자씩 나누어 Postfix함수로 전달하기.
void Postfix_play(Stack stack, string input_str){
for(int i = 0; i < input_str.size() && input_str.at(i) != '#'; i++)
{
Postfix(stack, input_str.at(i));
cout<<Top<int>(stack, true)<<' '; // Top은 스택의 값을 하나씩 프린트하는 용도
}
cout<<endl<<Top<int>(stack, true); //마지막 남은 값 출력
}
int main(int argc, const char * argv[])
{
// insert code here...
//FILE * file = fopen(argv[1], "r");
string equation;
cout<<"input equation : ";
cin>>equation;
equation += '#';
cout<<equation<<endl;
Stack stack;
//string input_str="4736%+*42/-9+23*-#";
//fgets(input_str, 101, file);
stack = CreateStack();
Infix_play(stack, equation);
cout<<endl;
DeleteStack(stack);
return 0;
}