您的位置:首页 > 其它

NYOJ-35 表达式求值

2012-08-02 23:57 330 查看

表达式求值

时间限制: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


/*
功能Function Description:     利用栈实现中序表达式   NYOJ-35

开发环境Environment:          DEV C++ 4.9.9.1
技术特点Technique:
版本Version:
作者Author:                   可笑痴狂
日期Date:                      20120802
备注Notes:
表达式 输入'='结束 支持浮点数
注意:
用exit(0) 提交会显示编译错误,没有<conin.h>头文件
*/

#include<cstdio>
#include<iostream>
#include<stack>
#include<cctype>
#include<cmath>
//#include<conio.h>    //exit(0);退出程序包含在#include<conio.h>   #include<stdlib.h>
//#include<cstdlib>
using namespace std;

stack<double> Opnd;        //操作数栈
stack<char> Optr;       //运算符栈

void Init()         //栈的初始化
{
while(!Opnd.empty())
Opnd.pop();
while(!Optr.empty())
Optr.pop();
Optr.push('=');    //先压入一个结束符‘=’
}

char Precede(char i,char j)     //判断i和j的优先级
{
switch(i)
{
case '+':
case '-':
if(j=='+'||j=='-'||j==')'||j=='=')
return '>';
else
return '<';
case '*':
case '/':
if(j=='(')
return '<';
else
return '>';
case '(':
if(j==')')
return '=';
//    else if(j=='=')
//        exit(0);
else
return '<';
case ')':
//    if(j=='(')
//        exit(0);
//    else
return '>';
case '=':
if(j=='=')
return '=';
//    else if(j==')')
//        exit(0);
else
return '<';
}
//    exit(0);
}

double Operate(double a,char i,double b)    //计算
{
switch (i)
{
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
case '/':
return a/b;
}
}

int judge(char c)         //判断---如果c为数字则返回1;若为小数点则返回2;如果c为操作符或者结束符则返回0;;
{
if(isdigit(c))
return 1;
else if(c=='.')
return 2;
else
return 0;
}

double EvaluateExpression(char *p)
{
double a,b,temp;
int flag;
char *st,*end,c,theta;  //定义操作符theta
Init();
c=*p;
while(c!='='||Optr.top()!='=')  //即当操作符栈和当前读入的字符都是‘=’时结束循环
{
if(isdigit(c))    //isdigit(c) 如果c是数字,则返回true;    isalpha(c) 如果c是字母,则为true;
{
temp=0;
flag=0;
for(;judge(c);c=*(++p))        //当不是数字或小数点时结束循环
{
if(judge(c)==1)            //说明是数字
{
temp=temp*10+c-'0';
if(c!=0)
end=p;
}
else                   //说明是小数点
{
st=p;        //记录下小数点的位置
end=p;    //记录小数点后最后一个非零数字的位置
flag=1;     //标记有小数点
}
}
if(flag)           //调整小数点的位置
temp=temp/pow(10,end-st);
Opnd.push(temp);        //记录的数字进栈
}
else
{
switch(Precede(Optr.top(),c))
{
case '<':     //栈顶元素优先权低
Optr.push(c);
c=*(++p);
break;
case '>':     //栈顶元素优先权高---退栈并将运算结果入栈
theta=Optr.top();
Optr.pop();
a=Opnd.top();
Opnd.pop();
b=Opnd.top();
Opnd.pop();
Opnd.push(Operate(b,theta,a));
break;
case '=':     //脱括号并接收下一字符
Optr.pop();
c=*(++p);
}
}
}
return Opnd.top();
}

int main()
{
int T;
char s[1000];
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
printf("%.2lf\n",EvaluateExpression(s));
}
return 0;
}


/*
功能Function Description:     利用栈实现中序表达式
开发环境Environment:          DEV C++ 4.9.9.1
技术特点Technique:
版本Version:
作者Author:                   可笑痴狂
日期Date:                 	 20120802
备注Notes:					表达式 输入'#'结束 只能处理整数之间的运算
*/

#include<cstdio>
#include<iostream>
#include<stack>
#include<cctype>
using namespace std;

stack<int> Opnd;        //操作数栈
stack<char> Optr;       //运算符栈

void Init()
{
while(!Opnd.empty())
Opnd.pop();
while(!Optr.empty())
Optr.pop();
Optr.push('#');    //将表达式起始符
}

char Precede(char i,char j)
{
switch(i)
{
case '+':
case '-':
if(j=='+'||j=='-'||j==')'||j=='#')
return '>';
else
return '<';
case '*':
case '/':
if(j=='(')
return '<';
else
return '>';
case '(':
if(j==')')
return '=';
else if(j=='#')
exit(0);
else
return '<';
case ')':
if(j=='(')
exit(0);
else
return '>';
case '#':
if(j=='#')
return '=';
else if(j==')')
exit(0);
else
return '<';
}
exit(0);
}

int Operate(int a,char i,int b)
{
switch (i)
{
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
case '/':
return a/b;
}
}

int EvaluateExpression(char *p)
{
int a,b,temp;
char c,theta;  //定义操作符theta
Init();
c=*p;
while(c!='#'||Optr.top()!='#')
{
if(isdigit(c))    //isdigit(c) 如果c是数字,则返回true;    isalpha(c) 如果c是字母,则为true;
{
temp=0;
for(;isdigit(c);c=*(++p))
temp=temp*10+(c-'0');
Opnd.push(temp);    //检测到有运算符,先把记录的数字进栈
}
else
{

switch(Precede(Optr.top(),c))
{
case '<':     //栈顶元素优先权低
Optr.push(c);
c=*(++p);
break;
case '>':     //栈顶元素优先权高---退栈并将运算结果入栈
theta=Optr.top();
Optr.pop();
a=Opnd.top();
Opnd.pop();
b=Opnd.top();
Opnd.pop();
Opnd.push(Operate(b,theta,a));
break;
case '=':     //脱括号并接收下一字符
Optr.pop();
c=*(++p);
}
}
}
return Opnd.top();
}

int main()
{
int T;
char s[1000];
scanf("%d",&T);
while(T--)
{
scanf("%s",s);
printf("%d\n",EvaluateExpression(s));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: