#include <stdio.h>

/* enum: 여러 종류 중 하나를 선택할 때 사용 
   struct: 여러 개의 서로 관련된 데이터를 한 덩어리로 묶을 때 사용 -> 동시에 존재
   후위표기식: token 현재 토큰의 종류가 무엇인지만 알면 됨 -> 현재 어떤 종류인지 하나만 저장하면 되기 때문에 enum을 사용하는 것
*/

typedef enum {
    lparen, rparen,
    plus, minus,
    times, divide,
    mod, eos, operand
} precedence; 

/*
symbol = 현재 읽은 실제 문자
token  = 그 문자의 종류
n      = 입력 수식에서 현재 읽는 위치
top    = 스택에서 현재 가장 위의 위치
*/

void add(int *top, element item)
{
    if (*top >= MAX_STACK_SIZE - 1) {
        stackFull();
        return;
    }

    stack[++(*top)] = item;
}

element delete(int *top)
{
    if (*top == -1) {
        return stackEmpty();
    }

    return stack[(*top)--];
}

char expr[] = "82/3-32*+";

int eval(void) // 후위 표기식을 계산해서 최종 결과를 반환하는 함수
{ 
    /* 전역변수로 되어 있는 후위 표기식 expr을 연산한다. '\0'은 수식의 끝을 나타
     낸다. stack과 top은 전역 변수이다. 함수 getToken은 토큰의 타입과 문자
     심벌을 반환한다. 피연산자는 한 문자로 된 숫자임을 가정한다. */
    
    precedence token; // 그 문자가 어떤 종류인지 저장
    char symbol; // 현재 읽은 실제 문자 하나를 저장
    int op1, op2, n = 0, top = -1; // n: 현재 몇 번째 문자를 읽고 있는지 나타내는 인덱스, top: 스택에서 가장 위쪽 데이터의 배열 인덱스
    token = get_token(&symbol, &n); //첫 번째 토큰 읽기


    /* 문자값을 숫자로 변경해주기위해서 symbol - '0' 실행, 컴퓨터는 문자 '8'를 내부적으로 숫자로 저장
    ASCII 코드
    '0' = 48
    '1' = 49
    ...
    '8' = 56
    '9' = 57
    '8' - '0' => 56 - 48 = 8 -> 진짜 숫자8이 됨
    */
    
    while (token != eos) { //문자열끝까지 반복
        if (token == operand) //토큰값이 피연산자라면
            add(&top, symbol-'0');  //stack push 문자열의 아스키값으로 변환하기위해서 symbol - '0'을해줌
        else { // 토큰값이 연산자라면 
            op2 = delete(&top);   // stack pop !! 먼저 꺼낸 값 = 오른쪽 피연산자, 반드시 뒷쪽부터 pop 왜? top값이 더 크다는건 더 위에 있다는 거니까 당연히 먼저 꺼내야햠 
            op1 = delete(&top);   // 다음 값 = 왼쪽 피연산자
            switch(token) { //두 피연산자를 꺼냈다면 현재 연산자가 무엇인지 검사 조건에 맞게 계산후 다시 stack push
                case plus: add(&top, op1+op2); break;
                case minus: add(&top, op1-op2); break;
                case times: add(&top, op1*op2); break;
                case divide: add(&top, op1/op2); break;
                case mod: add(&top, op1%op2);
            }
        }
        token = get_token(&symbol, &n); //각 문자를 처리한 다음 반드시 다음 문자 가져오기
    }
    return delete(&top); /* return result delete()를 통해 1을 꺼내 반환*/ 
}

/* get_token: 그 문자가 어떤 종류인지 저장 */
/* 수식에서 문자 하나를 읽고, 그 문자가 무엇인지 분류 */
precedence get_token(char *symbol, int*n) // &symbol, &n 변수의 주소
{
    /*현재 읽은 실제 문자 하나를 저장 
    후위 증가 연산자이므로 현재 값을 사용한 후 1 증가
    *symbol = expr[*n]; expr:후위표기식 예) 83/2+
    (*n)++;
    */
    *symbol = expr[(*n)++]; // 현재 읽은 실제 문자 하나를 저장, 후위 증가 연산자이므로 현재 값을 사용한 후 1 증가
    switch (*symbol) { //읽은 문자가 무엇인지 검사
        case '(' : return lparen;
        case ')' : return rparen;
        case '+' : return plus;
        case '-' : return minus;
        case '/' : return divide;
        case '*' : return times;
        case '%' : return mod;
        case '\0' : return eos;
        default   : return operand;
        /*no error checking, default is operand */
    }
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: