zoukankan      html  css  js  c++  java
  • 中缀表达式计算器

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

    例如       中缀表达式->(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.
    ");
            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.
    "); 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 '': 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 '';      //结束符号
            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] = '';
    
    }
    
    //计算后缀表达式
    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
    ", result);
    
        return 0;
    }
  • 相关阅读:
    20200924-4 代码规范,结对要求
    20200924-2 功能测试
    20200917-1 每周例行报告
    20200917-3 白名单
    20200917-2 词频统计 已更新附加题!
    20200910-1 每周例行报告
    20200924-2功能测试
    20200924-1每周例行报告
    20200924-3单元测试
    20200924-5 四则运算,结对
  • 原文地址:https://www.cnblogs.com/kernel0815/p/3454931.html
Copyright © 2011-2022 走看看