nyoj35 表达式求值

表达式求值

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 4
描述
ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。
比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)
输入
第一行输入一个整数n,共有n组测试数据(n<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。
数据保证除数不会为0
输出
每组都输出该组运算式的运算结果,输出结果保留两位小数。
样例输入
2
1.000+2/4=
((1+2)*5+1)/4=
样例输出
1.50
4.00




来源

数据结构课本例题改进


经典的表达式求值题,两种解题思路,第一种是先把前缀表达式转化成后缀表达式,再用后缀表达式求解,第二种是不转化,在遍历表达式的过程中求解

代码1:直接运算

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
 
# include <stdio.h>
# include <math.h>
# include <string.h>
# include <stack>

using  namespace std;

char s[ 1005];
stack< double> dtack;
stack< char> ctack;
int main( void)
{
     int n;
    scanf( "%d", &n);
     while (n--)
    {
        scanf( "%s", &s[ 1]);
         int len = strlen(&s[ 1]);
        s[ 0] =  '(';
        s[len] =  ')';
         int i;
         for (i =  0; i <= len; i++)
        {
             if (s[i] ==  '(')
            {
                ctack.push(s[i]);
            }
             else  if (s[i] >=  '0' && s[i] <=  '9')
            {
                 double v =  0. 0;
                 int spot =  0// 用以记录小数点的位置
                 while (s[i] >=  '0' && s[i] <=  '9' || s[i] ==  '.')
                {
                     if (s[i] ==  '.')
                    {
                        spot = i;
                    }
                     else
                    {
                        v = v *  10 + (s[i] -  '0');
                    }
                    i++;
                }
                i--;
                 if (spot ==  0)
                {
                    dtack.push(v);
                }
                 else
                {
                    dtack.push(v / pow( 10, (i - spot)));
                }
            }
             else  if (s[i] ==  '+' || s[i] ==  '-')
            {
                 while (ctack.top() !=  '(')
                {
                     double a = dtack.top(); dtack.pop();
                     double b = dtack.top(); dtack.pop();
                     double c =  0. 0;
                     switch(ctack.top())
                    {
                     case  '+' :
                        c = b + a;
                         break;
                     case  '-' :
                        c = b - a;
                         break;
                     case  '*' :
                        c = b * a;
                         break;
                     case  '/' :
                        c = b / a;
                         break;
                    }
                    dtack.push(c);   //把计算的结果压入栈中
                    ctack.pop(); //弹出运算过的运算符
                }
                ctack.push(s[i]);
            }

             else  if (s[i] ==  '*' || s[i] ==  '/')
            {
                 if (ctack.top() ==  '*')
                {
                     double a = dtack.top(); dtack.pop();
                     double b = dtack.top(); dtack.pop();
                    dtack.push(b * a);
                    ctack.pop();
                }
                 else  if (ctack.top() ==  '/')
                {
                     double a = dtack.top(); dtack.pop();
                     double b = dtack.top(); dtack.pop();
                    dtack.push(b / a);
                    ctack.pop();
                }
                ctack.push(s[i]);
            }

             else  if (s[i] ==  ')')
            {
                 while (ctack.top() !=  '(')
                {
                     double a = dtack.top(); dtack.pop();
                     double b = dtack.top(); dtack.pop();
                     double c =  0. 0;
                     switch (ctack.top())
                    {
                     case  '+' :
                        c = b + a;
                         break;
                     case  '-' :
                        c = b - a;
                         break;
                     case  '*' :
                        c = b * a;
                         break;
                     case  '/' :
                        c = b / a;
                         break;
                    }
                    dtack.push(c);
                    ctack.pop();
                }
                ctack.pop();
            }
        }
        printf( "%.2lf\n", dtack.top());
        dtack.pop();
    }
     return  0;
}
         

代码2:先转表达式

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <bits/stdc++.h>
using  namespace std;
const  int maxn= 1000+ 5;
string s1,s2;
stack< char> s; ///表达式转化的时候用到
stack< double> c; ///表达式求值的时候用到

void init()
{
     ///对两个栈进行初始化
     while(!s.empty())
        s.pop();
     while(!c.empty())
        c.pop();
}
int pro( char ch)
{
     ///规定运算符的优先级
     switch(ch)
    {
     case  '+':
     case  '-':
         return  1;
     case  '*':
     case  '/':
         return  2;

     default :
         return  0;
    }
}
void deal()
{
    init();
     int i= 0,len=s1.length();
    s.push( '#');
     while(i<len- 1)
    {
         if(s1[i]== '(')
            s.push(s1[i++]);
         else  if(s1[i]== ')')
        {
             while(s.top()!= '(')
            {
                s2+=s.top();
                s2+= ' ';
                s.pop();
            }
            s.pop(); ///把‘(’弹出
            i++;
        }
         else  if(s1[i]== '+'||s1[i]== '-'||s1[i]== '*'||s1[i]== '/')
        {
             while(pro(s.top())>=pro(s1[i]))
            {
                s2+=s.top();
                s2+= ' ';
                s.pop();
            }
            s.push(s1[i]); ///弹出完成后,把这个运算符压栈
            i++;
        }
         else
        {
             while(s1[i]<= '9'&&s1[i]>= '0'||s1[i]== '.')
                s2+=s1[i++];
            s2+= ' ';
        }
    }
     while(s.top()!= '#')
    {
         ///算式读完后,把栈清空
        s2+=s.top();
        s.pop();
        s2+= ' ';
    }
     ///到此,中缀表达式已转换为后缀表达式。
}
double countt()
{
     ///进行后缀表达式的计算
     int len=s2.length(),i= 0;
     double x;
     while(i<len)
    {
         if(s2[i]== ' ')
            i++;
         else
        {
             switch(s2[i])
            {
             case  '+':
                x=c.top();
                c.pop();
                x+=c.top();
                c.pop();
                i++;
                 break;
             case  '-':
                x=c.top();
                c.pop();
                x=c.top()-x;
                c.pop();
                i++;
                 break;
             case  '*':
                x=c.top();
                c.pop();
                x*=c.top();
                c.pop();
                i++;
                 break;
             case  '/':
                x=c.top();
                c.pop();
                x=c.top()/x;
                c.pop();
                i++;
                 break;
             default :
            {
                 int spot= 0;
                x= 0. 0;
                 while(s2[i]<= '9'&&s2[i]>= '0'||s2[i]== '.')
                {
                     if(s2[i]== '.')
                        spot=i;
                     else
                        x=x* 10+(s2[i]- '0');
                    i++;
                }
                 if(spot!= 0)
                    x=x/pow( 10,i-spot- 1);
            }
            }
            c.push(x);
        }
    }
     return c.top();
}

int main()
{
     int t;
    cin>>t;
     while(t--)
    {
        cin>>s1;
        s2= "";
        deal();
        printf( "%.2lf\n",countt());
    }
     return  0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值