博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
支持浮点数的表达式求值
阅读量:4216 次
发布时间:2019-05-26

本文共 4484 字,大约阅读时间需要 14 分钟。

包含加减乘除,支持括号运算,以及简单的非法表达式判断

原理:

只有当前操作符的优先级高于操作符栈栈顶的操作符的优先级,才入栈,否则弹出操作符以及操作数进行计算直至栈顶操作符的优先级低于当前操作符,然后将当前操作符压栈。当所有的操作符处理完毕(即操作符栈为空时),操作数栈中剩下的唯一一个元素便是最终的表达式的值。而操作符的优先级为:+和-优先级是一样的,*和/优先级是一样的,+、-的优先级低于*、/的优先级。

 不过需要注意的是在求值之前需要对表达式进行预处理,去掉空格、识别 负号(区分“-”是作为减号还是负号),提取操作数等。

这里符号在预处理的时候用#代替

#include
using namespace std;const char opt[] = {'+','-','*','/','#'};string preProcess(string str) { string exp; int len_str = str.size(); char *p = (char*)malloc(sizeof(char)*(len_str+1)); int i = 0, j = 0; while(i < len_str){ if(str[i] == ' '){ ++i; continue; } p[j++] = str[i++]; } p[j] = '\0'; return p; }bool isNum(string digit){ char c; bool flag; for(int i = 0; i < digit.size(); ++i){ c = digit[i]; if(c != '.' && (c <'0' || c > '9') ) return false; } return true;} vector
separation(string str){ //把字符串分割为数字 每个数字为一个string对象 string t=""; vector
exp; for(int i = 0; i < str.size(); ++i){ if(isdigit(str[i]) || str[i] == '.'){ t += str[i]; } else{ if(t.size() == 0){ //第一个字符不是数字的情况 t = str[i]; exp.push_back(t); } else{ exp.push_back(t);//把数字加入exp t = str[i]; exp.push_back(t);//把非数字加入exp } t =""; } } if(t.size() > 0){ //最后一组是数字的时候需要特殊处理 exp.push_back(t); } vector
res; for(int i = 0; i < exp.size(); ++i){ if(exp[i] == "-"){ if(i > 0 && (isNum(exp[i-1]) || exp[i-1] == ")")) res.push_back(exp[i]);//表示减号 else res.push_back("#");//表示负号 } else{ res.push_back(exp[i]); } } return res;} char compare(char a, char b){ char table[8][8] = { { ' ', '+', '-', '*', '/', '(', ')', '#' }, { '+', '>', '>', '<', '<', '<', '>', '<' }, { '-', '>', '>', '<', '<', '<', '>', '<' }, { '*', '>', '>', '>', '>', '<', '>', '<' }, { '/', '>', '>', '>', '>', '<', '>', '<' }, { '(', '<', '<', '<', '<', '<', '=', ' ' }, { ')', '>', '>', '>', '>', ' ', '>', '<' }, { '#', '>', '>', '>', '>', '>', ' ', '=' } }; //优先级表格 int i = 0,j = 0; for(j = 0; j < 8; ++j){ if(table[0][j] == b) break; } for(i = 0; i < 8; ++i){ if(table[i][0] == a) break; } return table[i][j];}bool isOpt(char c){ for(int i = 0; i < 5; ++i){ if(c == opt[i]) return true; } return false;}double calculate(stack
&opdSt, char opt) { double res; if(opt == '#'){ double opd = opdSt.top(); opdSt.pop(); res = 0-opd; opdSt.push(res); } else if(opt == '+'){ double rOpd = opdSt.top(); opdSt.pop(); double lOpd = opdSt.top(); opdSt.pop(); res = lOpd + rOpd; opdSt.push(res); } else if(opt == '-'){ double rOpd = opdSt.top(); opdSt.pop(); double lOpd = opdSt.top(); opdSt.pop(); res = lOpd - rOpd; opdSt.push(res); } else if(opt == '*'){ double rOpd = opdSt.top(); opdSt.pop(); double lOpd = opdSt.top(); opdSt.pop(); res = lOpd * rOpd; opdSt.push(res); } else if(opt == '/'){ double rOpd = opdSt.top(); opdSt.pop(); double lOpd = opdSt.top(); opdSt.pop(); res = lOpd*(1.0) / rOpd; opdSt.push(res); } }double getNum(string strNum){ return atof(strNum.c_str());}bool check(string str){ for(int i = 0; i < str.size(); ++i){ if(!isOpt(str[i]) && !isdigit(str[i]) && str[i] != '.' && str[i] != '(' && str[i] != ')') return false; if(str[i] == '#') return false; } return true;}double calExpress(string str) { vector
exp; exp = separation(str); int size = exp.size(); stack
opdSt; stack
optSt; string topOpt; for(int i = 0; i < size; ++i){ string c = exp[i]; if(isOpt(c[0])){ if(optSt.size() == 0){ optSt.push(c); } else{ string topOpt = optSt.top(); if(compare(topOpt[0],c[0]) == '>'){ //栈顶优先级不小于 该优先级 while(compare(topOpt[0],c[0]) == '>'){ optSt.pop(); calculate(opdSt,topOpt[0]); if(optSt.size() > 0){ topOpt = optSt.top(); } else{ break; } } optSt.push(c);//把取出的c入栈 (经过前面计算,目前c优先级大于栈顶元素); } else{ optSt.push(c); } } } else if(c == "("){ optSt.push(c); } else if(c == ")"){ topOpt = optSt.top(); while(topOpt != "("){ calculate(opdSt,topOpt[0]); optSt.pop(); topOpt = optSt.top(); } optSt.pop(); } else{ //操作数 直接入操作数栈 opdSt.push(getNum(c)); } } while(!optSt.empty()){ string topOpt = optSt.top(); calculate(opdSt,topOpt[0]); optSt.pop(); } return opdSt.top(); }int main() { string str; printf("请输入运算表达式:\n"); while(getline(cin,str)){ string res = preProcess(str); if(!check(res)){ cout << "非法表达式,请检查是否含有非法字符或中文字符\n\n"; printf("请输入运算表达式:\n"); continue; } printf("%s = %.2lf\n\n",str.c_str(),calExpress(str)); printf("请输入运算表达式:\n"); } return 0; }

转载地址:http://primi.baihongyu.com/

你可能感兴趣的文章
Conclusion for Constructors,Destructors,and Assignment Operators
查看>>
Conclusion for Accustoming Yourself to C++
查看>>
面试题1:赋值运算函数(offer)
查看>>
Mark : MessagePack简介及使用
查看>>
Mark : hive文件存储格式
查看>>
mark : hadoop 四种压缩格式
查看>>
All Things OpenTSDB
查看>>
单例模式(singleton),工厂方法模式(factory),门面模式(facade)
查看>>
抽象模式,适配器模式(Adapter),模板方法模式(Template method)
查看>>
建造者模式(builder),桥梁模式(bridge mode),命令模式(Command mode)
查看>>
装饰模式(Decorator),迭代器模式(Iterator),组合模式(composite)
查看>>
观察者模式(Observer),责任链模式,访问者模式(Visitor)
查看>>
状态模式(State)
查看>>
快速排序
查看>>
插入算法
查看>>
希尔排序
查看>>
选择排序
查看>>
归并排序
查看>>
归并排序
查看>>
插入排序进行链表排序
查看>>