中序表达式--C语言实现

主体程序:

/* calc_expr.c */

/************************************************************************
 *                                                                      
 *                        计算中序表达式demo程序
 * nizqsut
 ************************************************************************/
#include
#include

#include "../libdc/stackar.h"
#include "../libdc/fatal.h"
#include "../include/expression.h"


static char infix[] = "a+b*c+(d*e+f)*g";

static char subfix[sizeof(infix)+1];



//static const char digitals[] = {'1','2','3',''
//}

static TOKEN_PRIO get_token_prio(char token){

    TOKEN_PRIO token_prio;
    
    if (is_digital(token)) {
        return DIGITAL;
    }
    if (is_char(token)) {
        return CH_TOKEN;
    }
    switch(token) {
        case '+':
        case '-':
            token_prio = ADD_SUB;
            break;

        case '*':
        case '/':
            token_prio = MULTI_DIV;
            break;

        case '(':
            token_prio = LEFT_BRACKET;
            break;

        case ')':
            token_prio = RIGHT_BRACKET;
            break;
       
        default:
            token_prio = UNKOWN_TOKEN;
    }
   
    return token_prio;
}



int expr_input(char *buf_in, int buf_len){
   
    char ch;
    int in_len;

    in_len = 0;
    while ( (ch = getchar()) != 0x0a ) {
        buf_in[in_len++] = ch;
        if (in_len == (buf_len - 1)) {
            Error("Goto max input!\n");
            return -1;
        }
    }
    buf_in[in_len] = 0;

    return 0;
}

/* 将字符串表达式转化为中缀表达式 */
int string2infix(char *str, TOKEN *tokens, int max_token){

    int value;
    //int token_cnt;
    TOKEN_PRIO    token_prio;
    TOKEN_PRIO    old_token_prio;

    old_token_prio = UNKOWN_TOKEN;
    //token_cnt = 0;
   
    value = 0;
    while (*str) {
        switch( (token_prio = get_token_prio(*str) ) ) {

        case DIGITAL:
                value *= 10;
                value += ch_to_dig(*str);
                old_token_prio = token_prio;
            break;

        case ADD_SUB:
        case MULTI_DIV:
        case LEFT_BRACKET:
        case RIGHT_BRACKET:
           

            if (DIGITAL == old_token_prio) {
                if ( !tokens) {
                    Error("Not tokens for use!");
                    return -1;
                }
                tokens->prio = DIGITAL;
                tokens->value = value;
                value = 0;
//                tokens = tokens->next;
                tokens++;
            }

            if ( !tokens) {
                Error("Not tokens for use!");
                return -1;
            }
            tokens->prio = token_prio;
            tokens->value = *str;
            //tokens = tokens->next;
            tokens++;
            break;

        default:
            Error("Unkown token type!");
            return -1;
        }

        str++;
        old_token_prio = token_prio;
    }

    if (DIGITAL == old_token_prio) {
        if ( !tokens) {
            Error("Not tokens for use!");
            return -1;
        }
        tokens->prio = DIGITAL;
        tokens->value = value;
    }

    return 0;
}

static void out2subfix(char ch){

    static int subfix_index = 0;

    subfix[subfix_index++] = ch;
}

static void token_copy(TOKEN *src, TOKEN *target){
    target->prio = src->prio;
    target->value = src->value;
}

/* 将中缀表达式编程后缀表达式 */
int infix2subfix(TOKEN *infix_token, TOKEN *subfix_token, STACK_OP stack_op){

    //STACK_OP stack_op;
//    TOKEN_PRIO    token_prio;
//    TOKEN_PRIO    last_token_prio;
    TOKEN    token;

    stack_op->make_empty(stack_op);
   
    while (infix_token->prio != UNKOWN_TOKEN) {
       
        switch( infix_token->prio) {
            case DIGITAL:
            //case CH_TOKEN:
                    //out2subfix(infix[i++]);
                //if (subfix_token) {
                    token_copy(infix_token,subfix_token++);
                    //subfix_token = subfix_token->next;
                    //subfix_token++;
                //}else{
                //    Error("Subfix token flow!");
                //    return -1;
                //}
                break;

            case MULTI_DIV:
            case ADD_SUB:
                while (1) {
                    if (stack_op->is_empty(stack_op)) {
                        stack_op->push(stack_op, *infix_token);
                        break;
                    }else{
                        /* 如果栈里面的操作符优先级比当前操作符优先级高或相等,则其弹出栈 */
                        if ( (stack_op->get_top(stack_op)).prio >= infix_token->prio ) {
                            //if (subfix_token) {
                                token = stack_op->pop(stack_op);
                                token_copy(&token, subfix_token++);
                                //token_copy( &(stack_op->pop(stack_op)), subfix_token++);
                            //    subfix_token = subfix_token->next;
                            //}else{
                            //    Error("Subfix token flow!");
                            //    return -1;
                            //}
                        }else{
                            stack_op->push(stack_op,*infix_token);
                            break;
                        }
                    }

                }
                break;

            case LEFT_BRACKET:
                stack_op->push(stack_op,*infix_token);
                break;

            case RIGHT_BRACKET:
                do {
                    if ( LEFT_BRACKET == (stack_op->get_top(stack_op)).prio ) {
                        stack_op->pop(stack_op);
                        break;
                    }
                    //if (subfix_token) {
                        token = stack_op->pop(stack_op);
                        token_copy(&token, subfix_token++);
                        //token_copy( &stack_op->pop(stack_op), subfix_token++);
                    //    subfix_token = subfix_token->next;
                    //}else{
                    //    Error("Subfix token flow!");
                    //    return -1;
                    //}
                } while(1);
                break;

            default:
                Error("Unkown token prio!\n");
                break;
        }
        infix_token++;
        //infix_token = infix_token->next;
    }

    while (!stack_op->is_empty(stack_op)) {
        //if (subfix_token) {
            //token = stack_op->get_top(stack_op);
            token = stack_op->pop(stack_op);
            token_copy(&token, subfix_token++);
            //token_copy( &stack_op->pop(stack_op), subfix_token++);
        //    subfix_token = subfix_token->next;
        //}else{
        //    Error("Subfix token flow!");
        //    return -1;
        //}
        //out2subfix(stack_op->pop(stack_op));
    }
   
    /* subfix 结束标志为 prio == UNKOWN_TOKEN*/
    subfix_token->prio = UNKOWN_TOKEN;
    return 0;
}

static int
calc_token(TOKEN *token, int operater, int operator){

    int        result;
   
    switch(token->prio) {
        case ADD_SUB:
        case MULTI_DIV:
            break;

        default:
            Error("Unkown operater type!");
        //    return -1;
            break;
    }

    switch(token->value) {
        case '+':
            result = operater + operator;
            break;

        case '-':
            result = operater - operator;
            break;

        case '*':
            result = operater * operator;
            break;

        case '/':
            result = operater / operator;
            break;

        default:
            //Error("Unkown operator value!");
            //return -1;
            break;
    }

    return result;
}
/************************************************************************/
/* 计算后缀表达式方法:                                                  */
/*       遇到操作数,压栈;遇到操作符,弹出需要的操作数做运算             */
/************************************************************************/
int calc_subfix(TOKEN *subfix, STACK_OP stack_op){

    int operater;    //操作数
    int operator;    //被操作数
    TOKEN    token;

    stack_op->make_empty(stack_op);

    while (subfix->prio != UNKOWN_TOKEN) {
        switch(subfix->prio) {
            case DIGITAL:
                stack_op->push(stack_op, *subfix);
                break;

            case ADD_SUB:
            case MULTI_DIV:
                operator = stack_op->pop(stack_op).value;
                operater = stack_op->pop(stack_op).value;
                token.value = calc_token(subfix,operater,operator);
                token.prio = DIGITAL;
                stack_op->push(stack_op,token);
                break;

            default:
                Error("Unkown token type!");
                break;
        }
        subfix++;
    }

    if ( !stack_op->is_empty(stack_op)) {
        token = stack_op->pop(stack_op);
        printf("Expression value equal:%d\n",token.value);
    }else{
        Error("Subfix error!");
        return -1;
    }
   
    return 0;
}

#define EXPR_INPUT_BUF_LEN    256
#define MAX_TOKEN    16
/*
"a+b*c+(d*e+f)*g"的后缀表达式为:
        a b c * + d e * f + g * +
"3+5*6+(18*24+17)/12" 后最表达式为:
        3 5 6 * + 18 24 * 17 + 12 / +       
*/               
int calc_expr(void){

    char buf_in[EXPR_INPUT_BUF_LEN]; //= "3+5*6+(18*24+17)/12";// = "11+12*13+(14*15+16)*17";
    STACK_OP stack_op;
    TOKEN    infix[MAX_TOKEN];
    TOKEN    subfix[MAX_TOKEN];
    int    i;

    if ( !(stack_op = stack_init(MAX_TOKEN)) ) {
        Error("Stack initial fail!");
        goto exit_calc_expr;
    }

    /*
    if ( !(infix = malloc(sizeof(struct TOKEN) * MAX_TOKEN)) ) {
        Error("Out of space!");
        goto free_stack_mem;
    }
    if ( !(subfix = malloc(sizeof(struct TOKEN) * MAX_TOKEN)) ) {
        Error("Out of space!");
        goto free_infix_mem;
    }*/

    for (i = 0; i < MAX_TOKEN; i++) {
        infix[i].prio = UNKOWN_TOKEN;
        subfix[i].prio = UNKOWN_TOKEN;
    }

    if (expr_input(buf_in,EXPR_INPUT_BUF_LEN)) {
        Error("Expression input error!");
        goto free_all_mem;
    }/**/

    if (string2infix(buf_in,infix,MAX_TOKEN)) {
        Error("String2infix error!");
        goto free_all_mem;
    }

    if (infix2subfix(infix,subfix,stack_op)) {
        Error("infix2subfix error!");
        goto free_all_mem;
    }

    if (calc_subfix(subfix,stack_op)) {
       
    }
free_all_mem:
//    free(subfix);
//free_infix_mem:
//    free(infix);
//free_stack_mem:
    stack_release(stack_op);
exit_calc_expr:
    return 0;
}

//----------------------------------------------------------------------------
表达式相应的头文件:

/* expression.h */

#ifndef __EXPRESSION_H__
#define __EXPRESSION_H__

#define true    1
#define false    0

#define is_digital(c)    ( ((c) >= '0') && ((c) <= '9') ) ? true : false

#define is_char(c)        ( ((c) >= 'a') && ((c) <= 'z') ) ? true : false

#define ch_to_dig(ch)    ( (ch) - '0' )

typedef enum {
    UNKOWN_TOKEN = 0,
    LEFT_BRACKET,
    RIGHT_BRACKET,
    DIGITAL,
    CH_TOKEN,
    ADD_SUB,
    MULTI_DIV,
//    LEFT_BRACKET,
//    RIGHT_BRACKET,
}TOKEN_PRIO;

typedef struct TOKEN{
    int    value;
    TOKEN_PRIO    prio;
    //TOKEN    *next;
}TOKEN;

//----------------------------------------------------------------------------
堆栈头文件:

/* stackar.h */
#ifndef __STACKAR_H__
#define __STACKAR_H__

/* 打开边界检查功能 */
#define    STACK_DEBUG       

#define MIN_STACK_SIZE    8
#define EMPTY_TOS    -1

#define STACK_TRUE    1
#define STACK_FALSE 0

#define EXPR_STACK
//--
//#ifndef element_type

//#ifdef EXPR_STACK
#include "../include/expression.h"
typedef struct TOKEN    element_type;
//#else
//typedef int element_type;
//#endif

//#endif
//--


typedef struct _STACK_OP *STACK_OP;

struct _STACK_OP{
    void    *priv;
    void    (*make_empty)(STACK_OP stack_op);
    int        (*is_full)(STACK_OP stack_op);
    int        (*is_empty)(STACK_OP stack_op);
    void    (*push)(STACK_OP stack_op, element_type element);
    element_type (*pop)(STACK_OP stack_op);
    element_type (*get_top)(STACK_OP stack_op);
    int (*get_capacity)(STACK_OP stack_op);
}_STACK_OP;

STACK_OP stack_init(int stack_capacity);
void stack_release(STACK_OP stack_op);

#endif


//----------------------------------------------------------------------------
堆栈的实现:

/* stackar.c */

#include "stackar.h"
#include "fatal.h"

struct _STACK_INFO {
    int capacity;
    int top_pos;    // top of stack
    element_type    *array;
}_STACK_INFO;

typedef struct _STACK_INFO *STACK_INFO;

static void make_empty(STACK_OP stack_op){
   
    STACK_INFO stack_info;
   
    stack_info = stack_op->priv;
    stack_info->top_pos = EMPTY_TOS;
}

/* If stack is full return STACK_TRUE, else return STACK_FALSE. */
static int is_full(STACK_OP stack_op){

    STACK_INFO stack_info;
   
    stack_info = stack_op->priv;

    return ( (stack_info->top_pos + 1) == stack_info->capacity ) ? STACK_TRUE : STACK_FALSE;
}

/* If stack is empty return STACK_TRUE, else return STACK_FALSE. */
static  int is_empty(STACK_OP stack_op){

    STACK_INFO stack_info;

    stack_info = stack_op->priv;

    return (stack_info->top_pos == EMPTY_TOS) ? STACK_TRUE : STACK_FALSE;
}

/* 先栈指针加一,再入栈。属于满栈 */
static void push(STACK_OP stack_op, element_type element){

    STACK_INFO stack_info;
   
    stack_info = stack_op->priv;

#ifdef STACK_DEBUG
    if (STACK_TRUE == stack_op->is_full(stack_op)) {
        Error("Stack have full. Can't push!");
        return;
    }
#endif

    stack_info->array[++stack_info->top_pos] = element;

    return;
}

/* 先出栈,再使栈指针减一 */
static element_type pop(STACK_OP stack_op){

    STACK_INFO stack_info;
   
    element_type    element;
   
    stack_info = stack_op->priv;

#ifdef STACK_DEBUG
    if (STACK_TRUE == stack_op->is_empty(stack_op)) {
        Error("Stack is empty. Cann't pop!");
        //return ;    /* avoid complier warning. */
    }
#endif
   
    element = stack_info->array[stack_info->top_pos];
    stack_info->top_pos--;
    return element;

    //return stack_info->array[stack_info->top_pos--];
}

/* 返回栈顶元素 */
static element_type get_top(STACK_OP stack_op){
    STACK_INFO stack_info;
   
    stack_info = stack_op->priv;

    return stack_info->array[stack_info->top_pos];
}

/* 返回整个栈容量 */
static int get_capacity(STACK_OP stack_op){
    STACK_INFO stack_info;
   
    stack_info = stack_op->priv;

    return stack_info->capacity;
}

/* 分配栈所需要的内存,初始化栈操作的函数指针
 * 如果初始化失败返回空指针
 */
STACK_OP stack_init(int stack_capacity){
   
    STACK_INFO    stack_info;
    STACK_OP    stack_op;

    if (stack_capacity < MIN_STACK_SIZE) {
        Error("Stack size is too small");
    }

    if ( !(stack_op = malloc(sizeof *stack_op)) ) {
        Error("Out of space!!");
        goto error_exit;
    }
   
    if ( !(stack_info = malloc(sizeof(*stack_info))) ) {
        Error("Out of space!!");
        goto free_stack_op;
    }
    if (!(stack_info->array=(element_type *)malloc( sizeof(element_type) * stack_capacity))) {
        Error("Out of space!!");
        goto free_stack_info;
    }

    stack_info->capacity = stack_capacity;
    stack_op->priv        = (void *)stack_info;
    stack_op->make_empty = make_empty;
    stack_op->push        = push;
    stack_op->pop        = pop;
    stack_op->is_empty    = is_empty;
    stack_op->is_full    = is_full;
    stack_op->get_capacity = get_capacity;
    stack_op->get_top    = get_top;
   
    stack_op->make_empty(stack_op);

    return stack_op;

free_stack_info:
    free(stack_info);
free_stack_op:
    free(stack_op);
error_exit:
    return NULL;
}

void stack_release(STACK_OP stack_op){

    STACK_INFO stack_info;
   
    stack_op->make_empty(stack_op);

    stack_info = stack_op->priv;
    free(stack_info->array);
    free(stack_info);
    free(stack_op);
   
    return;
}
 
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(446) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值