Native/C

계산기

aucd29 2013. 10. 2. 18:51
// 중위 -> 후위로 그리고 과정 보여주고 계산값 보여주고

#include <stdio.h>

//
// defintion
//
#define MAX_STACK_SIZE 100
#define MAX_EXPR_SIZE 100
typedef enum{
    lparen, rparen, plus, minus, times, divide, mod, eos, operand
}precedence;

//
// variant value
//
int stack[MAX_STACK_SIZE];
char expr[MAX_EXPR_SIZE];
double num_stack[MAX_STACK_SIZE];

static int isp[] = {0, 19, 12, 12, 13, 13, 13, 0};
static int icp[] = {20, 19, 12, 12, 13, 13, 13, 0};

//
// function
//
/*int eval(void);*/
precedence get_token(char*, int*);
void postfix(void);
void getline(char *);
void print_token(precedence);
precedence remove(int *):
void add(int*, precedence);

int main(int argc, char *argv[])
{
    //
    // 중위 표기식 입력 받고
    //
    getline(expr);

    //
    // 중위식을 후위식으로 바꾸고
    //
    postifx();


    return 0;
}

//
// 배열에 주소에 내용을 입력 받는다.
//
void getline(char *s)
{
    int c, i;

    for(i=0;(c=getchar()) !='\n'; ++i)
        if(c!=' ' && MAX_EXPR_SIZE>i) *s++ = c;
    s = '\0';
}

//
// 중위 표기를 후위표기로 변환한다.
//
void postifx(void)
{
    char symbol[100];
    char *FirstSymbol = symbol;
    precedence token;
    int n = 0;
    int top = 0;        // insert eos
    int num_top = 0;
    stack[0] = eos;

    for(token = get_token(symbol, &n); token != eos; token = get_token(symbol, &n))
    {
        if(token == operand)
        {
            *symbol = '\0';
            printf("%s", symbol);
            //num_stack[num_top++] = atof(symbol);
        }
        else if(token == rparen)
        {
            print_token(remove(&top));
            remove(&top);    // remove rparen;
        }
        else
        {
            // symbol 의 isp가 token의 icp보다 크거나 작으면 symbol을 제거하고 출력한다.

            while(isp[stack[top]] >= icp[token])
                print_token(remove(&top));
            add(&top, token);
        }

        symbol = FirstSymbol;    // init
    }

    while((token = remove(&top)) != eos)
        print_token(token);

    printf("\n");
}

precedence get_token(char* symbol, int* n)
{
    char c;
    
    switch(c = expr[(*n)++])
    {
    case '-':
    //    if(n-1==0 || get_token(expr[*n-2], n) != openrand)
    //    {
    //        *symbol++ = '-';
    //        return get_token(symbol, n);
    //    }
    //    else
            return minus;
    case '(':    return lparen;
    case ')':    return rparen;
    case '+':    return plus;
    case '/':    return divide;
    case '*':    return times;
    case '%':    return mod;
    case '\0':    return eos;
    default:
        *symbol++ = c;
        while(get_token(symbol, n)==openrand);
            //*symbol++ = c;        
        return openrand;
    }
}

void print_token(precedence n)
{
    switch(n)
    {
    case minus:        printf("-"); break;
    case lparen:    printf("("); break;
    case rparen:    printf(")"); break;
    case plus:        printf("+"); break;
    case divide:    printf("/"); break;
    case times:        printf("*"); break;
    case mod:        printf("%");break;
    case eos:        printf("\0");break;
    }
}

precedence remove(int* top)
{
    --*top;
    return stack[*top];
}

void add(int* top, precedence token)
{
    stack[++*top] = token;
}


/*
int eval(void)
{
    precedence token;
    char symbol;
    int op1, op2;
    int n = 0;
    int top = -1;
    token = get_token(&symbol, &n);
    while(token != eos)
    {
        if(token == operand)
            add(&top, symbol - '0'); // insert stack
        else
            op2 = remove(&top); // delete stack

        op1 = remove(&top);
        switch(token)
        {
        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);
            break;
        }
    }
    token = get_token(&symbol, &n);

    return remove(&top);    // return result
}


*/