NYOJ 35 表达式求值 or 267 郁闷的C小加(二)

来源:互联网 发布:全球云计算公司排名 编辑:程序博客网 时间:2024/06/05 14:28
描述

聪明的你帮助C小加解决了中缀表达式到后缀表达式的转换(详情请参考“郁闷的C小加(一)”),C小加很高兴。但C小加是个爱思考的人,他又想通过这种方法计算一个表达式的值。即先把表达式转换为后缀表达式,再求值。这时又要考虑操作数是小数和多位数的情况。

输入
第一行输入一个整数T,共有T组测试数据(T<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数并且小于1000000。
数据保证除数不会为0。
输出
对于每组测试数据输出结果包括两行,先输出转换后的后缀表达式,再输出计算结果,结果保留两位小数。两组测试数据之间用一个空行隔开。
样例输入
21+2=
(19+21)*3-4/5=
样例输出
12+=
3.00

1921+3*45/-=
119.20


这是栈的经典题目,虽说并不难,还是有一些操作性,

这两道题卡了好久一直没做出来,主要是将后缀表达式建好,

考虑以下几种情况:

1.当前符号为(,那么直接入栈

2.当前符号为+ -,那么栈顶乘除出栈(如果有),然后判断

现在的栈顶是否为+ -,如果是入栈。(不能先出加减再出乘除,例如栈中是+*)

(23的当前符号都要入栈)

3.当前符号为* /,栈顶的乘除出栈

4.数字或小数点就全部就加入就行了。

5.当前符号为),和第2步一样。

这样后缀表达式出来就只要算出来就行了。

#include <stdio.h>#include <stack>#include <string.h>const int maxn = 10005;using namespace std;char str[maxn], suffix[maxn], tch[maxn];int is_NumOrP ( char ch ){    return ch == '.' || ch >= '0' && ch <= '9';}int is_opera ( char ch ){    return ch == '+' || ch == '-';}int is_opers ( char ch ) { return  ch == '*' || ch == '/'; }double to_Double ( char str[], int i, int j )   //转成小数{    int k;    double ret = 0, b = 0.1;    for ( k = i; k <= j; k ++ )    {        if ( str[k] == '.' )            break ;        ret = ret*10+( str[k]-'0' );    }    k ++;    while ( k <= j )    {        ret += ( str[k]-'0' )*b;        b *= 0.1;        k ++;    }    return ret;}double opera ( double a, double b, char ch ){    switch ( ch )   //运算    {        case '+' :            return a+b;        case '-' :            return a-b;        case '*' :            return a*b;        case '/' :            return a/b;    }    return 0;}void print ( char str[] ){    int len = strlen ( str );    for ( int i = 0; i < len; i ++ )        if ( str[i] != ' ' )            printf ( "%c", str[i] );    puts ( "=" );}int main ( ){    int T, pos, cas = 0;    stack < double > val;    stack < char > op;    scanf ( "%d", &T );    while ( T -- )    {        pos = 0;        while ( ! val.empty ( ) )   val.pop ( );        while ( ! op.empty ( ) )    op.pop ( );        scanf ( "%s", str );        for ( int i = 0; str[i] != '='; i ++ )        {            if ( str[i] >= '0' && str[i] <= '9' )            {                while ( str[i] != '=' && is_NumOrP ( str[i] ) )                {                    suffix[pos ++] = str[i];                    i ++;                }                suffix[pos ++] = ' ';                i --;            }            else if ( str[i] == '(' )                op.push ( str[i] );            else if ( is_opers ( str[i] ) ) //乘除前面有乘除就将其放入后缀表达式            {                if ( ! op.empty ( ) && is_opers ( op.top ( ) ) )                {                    suffix[pos ++] = op.top ( );                    suffix[pos ++] = ' ';                    op.pop ( );                }                op.push ( str[i] );            }            else if ( is_opera ( str[i] ) )            {   //加减前面有乘除就加入后缀                if ( ! op.empty ( ) && is_opers ( op.top ( ) ) )                {                    suffix[pos ++] = op.top ( );                    suffix[pos ++] = ' ';                    op.pop ( );                }   //去掉乘除(有) 前面一个是加减也将其加入后缀                if ( ! op.empty ( ) && is_opera ( op.top ( ) ) )                {                    suffix[pos ++] = op.top ( );                    suffix[pos ++] = ' ';                    op.pop ( );                }                op.push ( str[i] );            }            else if ( str[i] == ')' )            {   //注意最后一个可能是乘除                if ( ! op.empty ( ) && ( op.top ( ) == '*' || op.top ( ) == '/' ) )                {                    suffix[pos ++] = op.top ( );                    suffix[pos ++] = ' ';                    op.pop ( );                }                int cnt = 0;    //前面实际上应该最多只有一个加减                while ( ! op.empty ( ) && op.top ( ) != '(' )                {                    tch[cnt ++] = op.top ( );                    op.pop ( );                }                if ( ! op.empty ( ) )                    op.pop ( );                for ( int j = cnt-1; j >= 0; j -- ) //逆序                {                    suffix[pos ++] = tch[j];                    suffix[pos ++] = ' ';                }            }        }   //最后栈中残余的符号,也要考虑最后一个乘除        if ( ! op.empty ( ) && ( op.top ( ) == '*' || op.top ( ) == '/' ) )        {            suffix[pos ++] = op.top ( );            suffix[pos ++] = ' ';            op.pop ( );        }        int cnt = 0;        while ( ! op.empty ( ) )    //这里其实最多也只有一个符号        {            tch[cnt ++] = op.top ( );            op.pop ( );        }        for ( int j = cnt-1; j >= 0; j -- )        {            suffix[pos ++] = tch[j];            suffix[pos ++] = ' ';        }        suffix[pos] = '\0';        //puts ( suffix );        if ( cas ++ )   //控制换行            printf ( "\n" );        print ( suffix );        for ( int i = 0; i < pos; i ++ )        {            if ( suffix[i] == ' ' ) //将空格continue                continue ;            if ( is_NumOrP ( suffix[i] ) )            {                int j = i;                while ( i < pos && is_NumOrP ( suffix[i] ) )                    i ++;                i --;                val.push ( to_Double ( suffix, j, i ) );            }            else            {                double b = val.top ( );                val.pop ( );                double a = val.top ( );                val.pop ( );                val.push ( opera ( a, b, suffix[i] ) );            }        }        printf ( "%.2lf\n", val.top ( ) );    }    return 0;}/*25-4+6/3*4=(5-(5-2*3+4))=*/



0 0
原创粉丝点击