中缀表达式计算器

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

例如       中缀表达式->(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;
}

 

posted on 2013-12-02 23:54 kernel_main 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/kernel0815/p/3454931.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值