#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 */
}
}
To embed this project on your website, copy the following code and paste it into your website's HTML: