赞
踩
使用C++自带的stack栈模板来实现四则运算表达式求值
算法描述参考第3.2.5节
算法伪代码参考P53-54的算法3.4
例如
1. Push (OPTR, '#');表示把字符#压入堆栈OPTR中,转换成c++代码就是OPTR.push('#');
2. Pop(OPND, a); 表示弹出栈OPND的栈顶元素,并把栈顶元素放入变量a中。因此改成c++代码是两个操作:a = OPND.top(); OPND.pop();
3. a = GetTop(OPND)表示获取栈OPND的栈顶元素,转成c++代码就是: a = OPND.top();
大家主要是改造表达式求值函数EvaluateExpression的代码
输入
第一个输入t,表示有t个实例
第二行起,每行输入一个表达式,每个表达式末尾带#表示结束
输入t行
输出
每行输出一个表达式的计算结果,计算结果用浮点数(含2位小数)的格式表示
参考代码如下:
#include <iostream>
#include<iomanip>
using namespace std;
int main()
{ double temp = 12.345678
cout<<fixed<<setprecision(2)<<temp<<endl;
}
输出结果为12.35
输入样例:
2
1+2*3-4/5#
(66+(((11+22)*2-33)/3+6)*2)-45.6789#
输出样例
6.20
54.32
这道题最重要的就是要把表达式转换成后缀表达式。比如,原表达式是= a * b + (c - d / e) * f就变为a b * c d e / - f * + ,这样运算符出现的顺序就正好是实际运算的顺序。那么怎么样把原表达式变为后缀表达式呢?用两个栈OPTR和OPND来分别运算符和数值,遍历表达式,当遇见数值时,直接入OPND。遇见运算符时,比较该运算符与栈顶运算符的优先级顺序,若该运算符的优先级高,入栈;否则,将OPND的上两个数取出来进行运算,并把运算结果存入OPND栈顶。
当读到#时说明该表达式结束,OPND中的元素就是最终的计算结果。
- #include <iostream>
- #include <string>
- #include <cstring>
- #include <stack>
- #include <iomanip>
- using namespace std;
-
- #define OPSETSIZE 7
- unsigned char Prior[7][7] = { //运算符间的优先关系
- '>','>','<','<','<','>','>',
- '>','>','<','<','<','>','>',
- '>','>','>','>','<','>','>',
- '>','>','>','>','<','>','>',
- '<','<','<','<','<','=',' ',
- '>','>','>','>',' ','>','>',
- '<','<','<','<','<',' ','='
- };
- char OPSET[OPSETSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'}; //运算符集合
-
- double Operate(double a, unsigned char theta, double b); //计算类似a+b的表达式结果
- bool In(char Test, char* TestOp); //判断字符Test是否是运算符,是则返回true
- char precede(char Aop, char Bop); //返回两个运算符优先级的比较结果
-
- //以下完成算术表达式求值函数EvaluateExpression(string MyExp)的填空
- double EvaluateExpression(string MyExp) //算术表达式求值算法
- //设OPTR和OPND分别为运算符栈和运算数栈
- //参数MyExp是表达式字符串
- { stack<char> OPTR; //运算符栈,字符元素
- stack<double> OPND; //运算数栈,实数元素
- char TempData[20];
- double Data,a,b, r;
- char theta, c,x,Dr[2];
- OPTR.push('#');
- strcpy(TempData,"\0");
- int i=0; //表达式字符串的当前字符位置
- c = MyExp[i]; //表达式字符串的当前字符
-
- //逐个读入表达式字符串的字符到变量c,并识别为数值或运算符,做相应处理
- while (c!='#'||OPTR.top()!='#') {
- // if (c == '#') {
- // // return OPND.top();
- // break;
- // }
- // if (OPTR.top() == '#') {
- // // return OPND.top();
- // break;
- // }
- if (In(c, Dr)) {
- switch (precede(OPTR.top(), c)) {
- case '<':
- OPTR.push(c);
- i++;
- c = MyExp[i];
- break;
- case '=':
- OPTR.pop();
- i++;
- c = MyExp[i];
- break;
- case '>': {
- theta = OPTR.top();
- OPTR.pop();
-
- b = OPND.top();
- OPND.pop();
- a = OPND.top();
- OPND.pop();
-
- OPND.push(Operate(a, theta, b));
- break;
- }
- }
- } else {
- string str;
- int k=0;
- while (1) {
-
- if (In(MyExp[i], Dr)) {
- TempData[k]='\0';
- break;
- }
-
- else {
- TempData[k]=MyExp[i];
- i++;
- k++;
- c=MyExp[i];
- }
- }
- sscanf(TempData, "%lf", &Data);
- OPND.push(Data);
-
- }
-
-
- }
- return OPND.top();
- } //这是函数EvaluateExpression的右花括号
- //函数EvaluateExpression的代码到此结束
-
-
- //以下填空完成其他函数的定义,包括函数Operate\函数In\函数precede
- //可以参考教材光盘中文件夹CHAP03的源代码ALGO0304.cpp,几乎照抄
- double Operate(double a, unsigned char theta, double b) {
- switch (theta) {
- case '+':
- return a + b;
- break;
- case '-':
- return a - b;
- break;
- case '*':
- return a * b;
- break;
- case '/':
- return a / b;
- break;
- default :
- break;
- }
- }
- bool In(char Test, char* TestOp) {
- for (int i = 0; i < OPSETSIZE; i++) {
- if (Test == OPSET[i]) return true;
- }
- return false;
- }
- char precede(char Aop, char Bop) {
- int a, b;
- for (int i = -0; i < OPSETSIZE; i++) {
- if (Aop == OPSET[i]) a = i;
- if (Bop == OPSET[i]) b = i;
- }
- return Prior[a][b];
- }
-
- //主函数
- int main()
- { string Exp;
- int t;
- double result;
- cin>>t;
- while (t--)
- { cin>>Exp;
- result=EvaluateExpression(Exp);
- cout<<fixed<<setprecision(2)<<result<<endl;
- }
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。