表达式求值(南阳理工—35)

来源:互联网 发布:手机离线对讲机软件 编辑:程序博客网 时间:2024/06/05 12:40

表达式求值

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


(一)题目链接:南阳理工23

解题思路:

中缀表达式转后缀表达式:首先将加、减、乘、除运算符进行优先级划分,括号为最高优先级,之后为乘除、再为加减,等号为最低优先级,方便利用栈将运算符利用特定规则进行转换。之后遍历字符串,如果为数字字符或者小数点运算符,则将其添加为后缀表达式,后加一个空格,方便之后sstreamstring流输入,如果是运算符字符,则将按照规则进行进栈或者出栈操作,进栈则将运算符压入栈顶,出栈操作则将运算符添加入后缀表达式,后加空格。


运算符规则:首先栈为空时将运算符进栈,之后遇到运算符时,将其与栈顶运算符比较,如果当前运算符优先级高于栈顶运算符,则将当前元素进栈;如果当前元素优先级低于栈顶元素,则不断出栈,直到栈中出现更低优先级或者栈为空,最后将该运算符进栈。特别的:如果是括号运算符,遇左括号,则进栈,如果遇到右括号,则出栈 栈中左括号及左括号以上所有的运算符,且右括号不进栈。


后缀表达式求值:通过以上步骤,可以得到后缀表达式字符串,且每个数字字符串和运算符字符用空格进行了分割,方便我们用streamstring进行操作,然后遍历后缀字符串,对于数字字符串,我们用 atof( )函数可将其转换为数字,同时进栈,如果遇到运算符,取栈顶元素进行相应运算,最后再将结果进栈,最后遇到等号运算符结束,当前栈中唯一栈顶元素即为表达式的值。

AC代码:

#include<cstdio>#include<cmath>#include<iomanip>#include<sstream>#include<stack>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int Judge(char ch){//运算符进行优先级划分 if(ch == '+') return 1;if(ch == '-') return 1;if(ch == '*') return 2;if(ch == '/') return 2;if(ch == '(') return 0;if(ch == ')') return 0;}int main (void){string str;string s;int count ;cin>>count;while(count--){int i=0 ;str.clear();s.clear() ;cin>>str;stack<char>mid; //字符串栈 ,用于中缀表达式转后缀表达式 stack<double>ans;//数字栈 ,用于后缀表达式求值 while(str[i] != '='){if(str[i] == '('){//判断,左括号进栈 mid.push(str[i]);i++;}else if( str[i] == ')')//遇右括号则将左括号及左括号以上标识符出栈 {while(mid.top()!='('){s = s + mid.top() ;s += ' ';mid.pop() ;}mid.pop() ;i++;}else if(isdigit(str[i]))//数字或小数点则直接转入后缀表达式 {while(str[i]<='9'&&str[i]>='0' || str[i] =='.'){s = s + str[i];i++;}s += ' ';}else if(str[i] == '+'||str[i] == '-'||str[i] == '*'||str[i] == '/'){while(!mid.empty() && Judge(mid.top()) >= Judge(str[i])){//当前运算标识符优先级低于栈顶元素,进行出栈操作 s = s + mid.top();s = s + ' ';mid.pop();}mid.push(str[i]);//将当前运算符进栈 i++;}}while(!mid.empty())//将最后剩余运算符出栈 {s = s + mid.top() ;s = s + ' ';mid.pop() ;}string temp;stringstream ss(s);char a[1000];double num;while(ss>>temp){if( isdigit(temp[0]) ){for(i=0;i<temp.length();i++)a[i] = temp[i];a[i] ='\0';//最后必须赋 '\0' 否则报错 num = atof(a);//将数字字符串转为数字//注意atof()函数不支持string类型,支持char()ans.push(num);//将数字进栈 }else{// 运算符操作 double x,y;x = ans.top();ans.pop();y = ans.top();ans.pop();//取出栈顶两位元素 ,进行相应操作 if(temp == "+") num = x + y;if(temp == "-") num = y - x;if(temp == "*") num = x * y;if(temp == "/") num = y / x;ans.push(num);//得到元素进栈 }}cout<< fixed <<setprecision(2)<<ans.top()<<endl;//输出两位小数; }}



原创粉丝点击