用操作符堆棧和操作數堆棧實現四則運算表達式

學習了用用操作符堆棧和操作數堆棧實現四則運算表達式的基本思想和實現後,在https://blog.csdn.net/cyq0318/article/details/78633752/的基礎上自己動手實現了一下,代碼全部在CodeBlocks 下測試通過。

堆棧實現代碼如下:

#ifndef _DATA_STRUCT_H
#define _DATA_STRUCT_H

typedef struct _NODE
{
    void *data;
    struct _NODE *next;
} NODE;

typedef struct _STACK
{
    NODE *top;
    int nd_size;
    int count;
} STACK;

void stack_init(STACK *s,int nd_size);
BOOL stack_empty(STACK *s);
void stack_push(STACK *s,void *data);
void* stack_pop(STACK *s);
void* stack_get_top(STACK *s);
char stack_ch_pop(STACK *s);
int stack_int_pop(STACK *s);
char stack_ch_peek(STACK *s);




#endif
​
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "define.h"
#include "data_struct.h"

void stack_init(STACK *s,int nd_size)
{
    s->top = NULL;
    s->nd_size = nd_size;
    s->count = 0;

    return;
}

BOOL stack_empty(STACK *s)
{
    return (s->top == NULL) ? R_TRUE:R_FALSE;
}

void stack_push(STACK *s,void *data)
{
    NODE *p = (NODE *)malloc(sizeof(NODE));

    assert(p);

    p->data = malloc(s->nd_size);
    memcpy(p->data,data,s->nd_size);

    p->next = s->top;
    s->top = p;
    s->count++;

    return;
}

void* stack_pop(STACK *s)
{
    void *data = NULL;

    if(s->top)
    {
        NODE *node = s->top;

        data = node->data;
        s->top = s->top->next;
        s->count--;

        free(node);
    }

    return data;
}

void* stack_get_top(STACK *s)
{
    void *data = NULL;

    if(s->top)
    {
        data = s->top->data;
    }

    return data;
}


char stack_ch_pop(STACK *s)
{
    void *data;
    char c;

    data = stack_pop(s);

    if(!data)
        return 0;

    c = *(char *)data;
    free(data);

    return c;
}

int stack_int_pop(STACK *s)
{
    void *data;
    int d;

    data = stack_pop(s);
    assert(data);
    d = *(int *)data;
    free(data);

    printf("stack_int_pop:pop %d\n",d);

    return d;
}

char stack_ch_peek(STACK *s)
{
    void *data;
    char c;

    data = stack_get_top(s);
    if(!data)
        return 0;

    c = *(char *)data;

    return c;
}



​

表達式實現代碼如下;

/*  求出四則運算表達式的值  */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include "define.h"
#include "data_struct.h"

#define LP          '('
#define RP          ')'
#define PLUS        '+'
#define MINUS        '-'
#define MUL         '*'
#define DIV         '/'


int expr_op_priority(char s)
{
    switch(s)
    {
    case '*':
    case '/':
        return 3;
    case '+':
    case '-':
        return 2;
    case '(':
    case ')':
        return 1;
    default:
        return 0;
    }
}

static int oper_nolower_pri(char new_op,char old_op)
{
    return expr_op_priority(new_op) >= expr_op_priority(old_op);
}


static void expr_pop_and_calc(STACK *s_op,STACK *s_num)
{
    char oper = stack_ch_pop(s_op);
    int  num2 = stack_int_pop(s_num);
    int  num1 = stack_int_pop(s_num);
    int  result;

    printf("%d %c %d\n",num1,oper,num2);

    switch(oper)
    {
    case '+':
        result = num1 + num2;
        break;
    case '-':
        result = num1 - num2;
        break;
    case '*':
       result = num1 * num2;
        break;
    case '/':
        result = num1/num2;
        break;
    }

    stack_push(s_num,&result);

    printf("push num:%d\n",result);

    return;
}


int math_expr(char *expr)
{
    STACK stack_op,stack_num;
    char *p = expr;
    int num;

    stack_init(&stack_op,sizeof(char));

    stack_init(&stack_num,sizeof(int));

    while(*p)
    {
        printf("begin parse %c\n",*p);

        if(isdigit(*p))
        {
            num = util_str2num(p);

            while(isdigit(*p))
                p++;

            printf("push num=%d\n",num);

            stack_push(&stack_num,&num);
        }
        else if(*p == LP)
        {
            printf("oper=%c\n",*p);
            stack_push(&stack_op,p);
            p++;
        }
        else if(*p == RP)
        {
            char last_oper = stack_ch_peek(&stack_op);
            printf("last oper=%c\n",last_oper);

             if(last_oper == LP)
                stack_pop(&stack_op);
             else
            {
                expr_pop_and_calc(&stack_op,&stack_num);

                last_oper = stack_ch_peek(&stack_op);

                if(last_oper == LP)
                    stack_pop(&stack_op);
                else
                    stack_push(&stack_op,p);
            }

            p++;

            last_oper = stack_ch_peek(&stack_op);
            printf("last oper111=%c\n",last_oper);

        }
        else
        {
            char last_oper,cur_oper = *p;

            last_oper = stack_ch_peek(&stack_op);

            printf("oper=%c,last_oper=%c\n",*p,last_oper);

            if(last_oper && oper_nolower_pri(last_oper,cur_oper))
            {
                expr_pop_and_calc(&stack_op,&stack_num);
            }

            stack_push(&stack_op,p);
            p++;
        }
    }


    while(!stack_empty(&stack_op))
    {
        char cur_op = stack_ch_pop(&stack_op);
        char last_op = stack_ch_peek(&stack_op);

        printf("cur op=%c,last op=%c\n",cur_op,last_op);

        if(last_op == LP && cur_op == RP)
            stack_pop(&stack_op);
        else if(!last_op)
        {
            stack_push(&stack_op,&cur_op);
            expr_pop_and_calc(&stack_op,&stack_num);
        }
        else if(oper_nolower_pri(last_op,cur_op))
            expr_pop_and_calc(&stack_op,&stack_num);

        if(cur_op == RP && last_op != LP)
            stack_push(&stack_op,&cur_op);
    }

    num = stack_int_pop(&stack_num);

    assert(stack_empty(&stack_num));
    assert(stack_empty(&stack_op));

    return num;
}

void math_expr_test(void)
{
    int result,expected_result;

    result = math_expr("((23+24)*2-34+(20-4))");
    expected_result = (23+24)*2-34+(20-4);
    assert(result == expected_result);


    result = math_expr("((1+1))");
    expected_result = (1+1);
    assert(result == expected_result);


    result = math_expr("12+23-45");
    expected_result = 12+23-45;
    assert(result == expected_result);

    result = math_expr("12+23-45+(78-23)");
    expected_result = 12+23-45+(78-23);
    assert(result == expected_result);

    result = math_expr("(235+24*5)");
    expected_result = (235+24*5);
    assert(result == expected_result);

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章