您的位置:首页 > 其它

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

2016-01-23 18:26 351 查看
描述
聪明的你帮助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;
}
/*
2
5-4+6/3*4=
(5-(5-2*3+4))=
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: