博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Qt之加减乘除四则运算-支持负数
阅读量:7211 次
发布时间:2019-06-29

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

一、效果展示

如图1所示,是简单的四则运算测试效果,第一列为原始表达式,第二列为转换后的后缀表达式,冒号后为结果。表达式支持负数和空格,图中是使用了5组测试数据,测试结果可能不全,如大家发现算法有问题,可留言,谢谢。

图1 四则运算展示

测试代码如下

1 void lineedit::CalculateExpression() 2 { 3     QString reExp("1 + 2.3 * (23 + 3)"); 4     QString res = change(reExp);//0 1 - 2.3 23 3 + * + 5  6     QString reExp2("1*(-3)+2*(3+3)"); 7     QString res2 = change(reExp2); 8  9     QString reExp3("2*-3+-2.1*(3+3)");10     repairExpress(reExp3);11     QString res3 = change(reExp3);12 13     QString reExp4("2*(-3)+-2.1*(3+3)");14     repairExpress(reExp4);15     QString res4 = change(reExp4);16 17     QString reExp5("2*(0-(1.1-3)*3)+-2.1*(3+3)");18     repairExpress(reExp5);19     QString res5 = change(reExp5);20 21     qDebug() << reExp << '\t'<< res << ":" << CalExp(res.split(' ', QString::SkipEmptyParts));22     qDebug() << reExp2 << '\t'<< res2 << ":" << CalExp(res2.split(' ', QString::SkipEmptyParts));23     qDebug() << reExp3 << '\t'<< res3 << ":" << CalExp(res3.split(' ', QString::SkipEmptyParts));24     qDebug() << reExp4 << '\t'<< res4 << ":" << CalExp(res4.split(' ', QString::SkipEmptyParts));25     qDebug() << reExp5 << '\t'<< res5 << ":" << CalExp(res5.split(' ', QString::SkipEmptyParts));26 }

二、一些小技巧

  在网上找了很多四则运算帖子,讲的都挺不错,思路很清晰,可是很少有拿来直接能用的,并且大多数的都不支持负数运算,既然是四则运算当然需要支持负数运算了,在这里我们只需要使用一点儿小技巧即可。

1、针对负号进行字符串修复 例如:-1*-3+2*(3+3) -> (0-1)*(0-3)+2*(3+3)。

1 //针对负号进行字符串修复 例如:-1*-3+2*(3+3) -> (0-1)*(0-3)+2*(3+3) 2 void repairExpress(QString & express) 3 { 4     bool repair = false; 5     int lpos = -1, rpos = -1; 6     QString result; 7     for(int i = 0; i < express.size(); ++i) 8     { 9         QChar c = express[i];10         if (c == '+' || c == '-' || c == '*' || c == '/')//出现符号时记录11         {12             if (repair)13             {14                 result.append(')');15                 lpos = -1;16                 repair = false;17             }18 19             if (c == '-'&&20                 (i == 0  || lpos != -1 && lpos == i - 1))21             {22                 result.append('(');23                 repair = true;24             }25 26             lpos = i;27         }28 29         result.append(c);30     }31 32     express = result;33 }

2、为了方便后续我们计算表达式,在中缀表达式转后缀表达式时,我们在数字和负号之间加了一个空格。

1 //数字和负号之间插入空格, 方便后续计算时分割2 void rettifyExpress(QString & express)3 {4     if (express.endsWith(' ') == false)5     {6         express.append(' ');7     }8 }

三、后缀表达式

中缀表达式:是一个通用的算术或逻辑公式表示方法, 是以中缀形式处于的中间(例:3 + 4),中缀表达式是人们常用的算术表示方法。

后缀表达式:后缀表达式,指的是不包含括号,放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则)。

中缀表达式转后缀表达式的方法:

1.遇到操作数:直接输出(添加到后缀表达式中)

2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
6.最终将栈中的元素依次出栈,输出。

下边我直接给出实现代码

1 //中缀表达式转后缀表达式 2 QString change(const QString & s_mid) 3 {   4     QString result; 5     QStack
stk; 6 7 QMap
op;//利用map来实现运算符对应其优先级 8 op['(']=0; 9 op[')']=0;10 op['+']=1;11 op['-']=1;12 op['*']=2;13 op['/']=2;14 auto iter = s_mid.begin();15 for(int i = 0; i < s_mid.size(); ++i)16 {17 QChar c = s_mid[i];18 if (c == ' ')19 {20 continue;21 }22 if (c == '-' &&23 (i == 0 || op.contains(s_mid[i-1])))//可能为负号24 {25 result.append('0');26 }27 if(op.contains(c))//判断该元素是否为运算符28 {29 if(c == ')')//情况230 {31 while(stk.top() != '(')32 {33 rettifyExpress(result);34 result.append(stk.top());35 stk.pop();36 }37 stk.pop();38 }39 else if(stk.empty() || c == '(' || op[c] > op[stk.top()])//情况1、情况340 {41 stk.push(c);42 }43 else if(op[c] <= op[stk.top()])//情况344 {45 while(op[c] <= op[stk.top()] && (!stk.empty()))46 {47 rettifyExpress(result);48 result.append(stk.top());49 stk.pop();50 if(stk.empty()) break;51 }52 stk.push(c);53 }54 55 rettifyExpress(result);56 }57 else58 {59 result.append(c);60 }61 }62 63 while(stk.empty() == false)//当中缀表达式输出完成,所有元素出栈64 {65 rettifyExpress(result);66 result.append(stk.top());67 stk.pop();68 }69 70 return result;71 }
View Code

四、表达式计算

通过后缀表达式计算时,我们就不需要考虑优先级了,只需要严格按照从左向右,遇到负号取之前的两个数值进行计算即可。

1 //计算表达式值 2 double CalExp(const QStringList & express) 3 { 4     double result; 5     QStack
stk; 6 for (int i = 0; i < express.size(); ++i) 7 { 8 QString item = express[i]; 9 if (item.size() == 1 && 10 (item.at(0) == "+" || item.at(0) == "-" || item.at(0) == "*" || item.at(0) == "/"))11 {12 double r = stk.pop().toDouble();13 double l = stk.pop().toDouble();14 switch(item.at(0).toLatin1())15 {16 case '+':17 result = l + r;break;18 case '-':19 result = l - r;break;20 case '*':21 result = l * r;break;22 case '/':23 result = l / r;break;24 }25 26 stk.push_back(QString::number(result));27 }28 else 29 {30 stk.push_back(item);31 }32 }33 34 return result;35 }

五、下载链接

  

参考文章:

1、

2、

 

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

你可能感兴趣的文章
js算法入门(3)--递归
查看>>
免费的局域网文档协作办公方式—onlyoffice文档协作
查看>>
微信支付HTTPS服务器证书验证(PHP)
查看>>
前端笔试题面试题记录(上)
查看>>
webpack4升级指北
查看>>
springboot整合shiro使用shiro-spring-boot-web-starter
查看>>
Express4.x api 翻译(draft)
查看>>
我为什么晚上写代码?
查看>>
React+Redux开发实录(一)搭建工程脚手架
查看>>
我来阅读lodash源码——Math(一)
查看>>
Laravel 5.5 使用 Passport 实现 Auth 认证
查看>>
用python写通用restful api service(一)
查看>>
javascript this指针详解
查看>>
Hystrix:HystrixCollapser请求合并
查看>>
three.js 入门详解(一)
查看>>
Android基础之Java接口
查看>>
Angular开发实践(一):环境准备及框架搭建
查看>>
Vue2 源码漫游(二)
查看>>
微信浏览器下拉黑边的终极解决方案---wScroollFix
查看>>
我是如何学会爱上 Vim 的
查看>>