• 단순한 방정식(예 : (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;
    }