中缀表达式计算器

中缀表达式的计算主要要转换为后缀表达式。

例如       中缀表达式->(1+2)*3-4         转换为后缀表达式   12+3*4-

至于后缀表达式的计算就很容易了     设定一个栈,然后后缀表达式从左到右一次进栈,如果当前的入栈的是数字就将其压入栈中,

如果是运算符,就从栈中弹出两个数字进行相应的运算,然后将运算后的数字压回栈中。当字符串完全处理之后,栈顶就是运算结果

PS:输入的后缀表达式是合法的才行。

那么中缀表达式如何转换为后缀表达式?(ch接受中缀表达式传递过来的字符)

1:ch 是'(' 放入栈;

2: ch 是 ‘)’一次输入栈中的运算符,直到遇到‘(’为止

3:如果ch是其它的合法字符,将ch与当前栈顶比较

    a:ch优先级高于栈顶元素,ch入栈

    b:ch 优先级低于或者等于 栈顶元素,输出栈顶元素,ch入栈

4:如果中缀表达式读取完成,依次输出栈中的元素直到栈空

 

 

举个例子:

对于中缀表达式 (A-B)/C+D

1 : '('进栈

2:A->压入输出字符

3:- 入栈

4:B 压入输出字符串

5: ')'一次输出栈里面的字符到输出字符串

6: ‘/’ 入栈

7: C 压入字符串

8: ’+‘    ’/‘出栈 然后’+‘入栈

9: D    压入输出字符串

10: 将栈中剩下的字符串依次输出

 

// calc.cpp : 定义控制台应用程序的入口点。

//



#include "stdafx.h"

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#define MAX_STACK_SIZE 100

#define MAX_EXPR_SIZE 100



void postfix(char *expr, char *outstr);

int eval(char *outstr);



typedef enum 

{

    lparen,

    rparen,

    pluss,

    minuss,

    timess,

    divide,

    mod,

    eos,

    operand 

} precedence;



int stack_int[MAX_STACK_SIZE];

precedence stack_prece[MAX_STACK_SIZE];

char expr[MAX_EXPR_SIZE];



int isp[] = { 1, 19, 12, 12, 13, 13, 13, 0 };

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



#define INT_ITEM 1

#define PRECE_ITEM 2



//入栈

void push(int *top, int a, precedence b, int flag)

{

    if (*top >= MAX_STACK_SIZE - 1)

    {

        printf("stack overflow.\n");

        exit(1);

    }

    //不同类型的元素进入不同的栈

    if (flag == INT_ITEM)

        stack_int[++*top] = a;

    else if (flag == PRECE_ITEM)

        stack_prece[++ *top] = b;

}



//出栈

void pop(int *top, int *a, precedence *b, int flag)

{

    if (*top < 0)

    {

        printf("stack overflow.\n"); exit(1);

    }

    //函数传进来的 a 和 b 分别接受不同的数值

    if (flag == INT_ITEM)

        *a = stack_int[(*top)--];

    else if (flag == PRECE_ITEM)

        *b = stack_prece[(*top)--];

}



//将运算符号转换为特定的符号

precedence get_token(char *symbol, int *n, char *expr)

{

    *symbol = expr[(*n)++];              // n 表示的是位置

    switch (*symbol)

    {

        case '(': return lparen;

        case ')': return rparen;

        case '+': return pluss;

        case '-': return minuss;

        case '*': return timess;

        case '/': return divide;

        case '%': return mod;

        case '\0': return eos;

        default: return operand;        //数字即被操作的符号

    }

}



//特定的符号转换为运算符号

char precedencetochar(precedence token)

{

    switch (token)

    {

        case pluss: return '+';

        case minuss: return '-';

        case divide: return '/';

        case timess: return '*';

        case mod: return '%';

        case eos: return '\0';      //结束符号

        default: return operand;    //数字

    }

}



//将中缀表达式转换为后缀表达式

void postfix(char *expr, char *outstr)

{

    char symbol;

    precedence token, precevalue;



    int n = 0;

    int intvalue;

    int i = 0;

    int top = -1;



    stack_prece[0] = eos;



    for (token = get_token(&symbol, &n, expr); token != eos; token = get_token(&symbol, &n, expr))

    {

        //如果取得的栈顶元素是数字存到新的数组中

        if (token == operand)

            outstr[i++] = symbol;

        //如果遇到括号

        else if (token == rparen){

            while (stack_prece[top] != lparen)

            {

                pop(&top, &intvalue, &precevalue, PRECE_ITEM);

                outstr[i++] = precedencetochar(precevalue);

            }

            pop(&top, &intvalue, &precevalue, PRECE_ITEM);

        }

        //如果入栈的运算符优先级比当前栈顶的优先级低,弹出当前栈顶

        else

        {

            if (top >= 0)

            while (isp[stack_prece[top]] >= icp[token])

            {

                pop(&top, &intvalue, &precevalue, PRECE_ITEM);

                outstr[i++] = precedencetochar(precevalue);

            }

            push(&top, 0, token, PRECE_ITEM);

        }

    }



    while (top >= 0)

    {

        pop(&top, &intvalue, &precevalue, PRECE_ITEM);

        outstr[i++] = precedencetochar(precevalue);

    }

    outstr[i] = '\0';



}



//计算后缀表达式

int eval(char *outstr)

{

    precedence token, precevalue;

    char symbol;



    int op1, op2, result;

    int n = 0;

    int top = -1;



    token = get_token(&symbol, &n, outstr);

    precevalue = token;



    while (token != eos)

    {

        if (token == operand)

        {

            push(&top, symbol - '0', precevalue, INT_ITEM);

        }

        else

        {

            pop(&top, &op2, &precevalue, INT_ITEM);

            pop(&top, &op1, &precevalue, INT_ITEM);



            switch (token)

            {

                case pluss: push(&top, op1 + op2, precevalue, INT_ITEM); break;

                case minuss: push(&top, op1 - op2, precevalue, INT_ITEM); break;

                case timess: push(&top, op1*op2, precevalue, INT_ITEM); break;

                case divide: push(&top, op1 / op2, precevalue, INT_ITEM); break;

                case mod: push(&top, op1%op2, precevalue, INT_ITEM); break;

                default: break;

            }

        }



        token = get_token(&symbol, &n, outstr);

    }

    pop(&top, &result, &precevalue, INT_ITEM);

    return result;

}



int _tmain(int argc, _TCHAR* argv[])

{

    char expr[100], outstr[100];

    int result;

    gets(expr);                          //输入的字符串

    postfix(expr, outstr);

    result = eval(outstr);

    printf("the result is %d\n", result);



    return 0;

}

 

你可能感兴趣的:(表达式)