一、效果展示

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

图1 四则运算展示

测试代码如下

 void lineedit::CalculateExpression()
{
QString reExp("1 + 2.3 * (23 + 3)");
QString res = change(reExp);//0 1 - 2.3 23 3 + * + QString reExp2("1*(-3)+2*(3+3)");
QString res2 = change(reExp2); QString reExp3("2*-3+-2.1*(3+3)");
repairExpress(reExp3);
QString res3 = change(reExp3); QString reExp4("2*(-3)+-2.1*(3+3)");
repairExpress(reExp4);
QString res4 = change(reExp4); QString reExp5("2*(0-(1.1-3)*3)+-2.1*(3+3)");
repairExpress(reExp5);
QString res5 = change(reExp5); qDebug() << reExp << '\t'<< res << ":" << CalExp(res.split(' ', QString::SkipEmptyParts));
qDebug() << reExp2 << '\t'<< res2 << ":" << CalExp(res2.split(' ', QString::SkipEmptyParts));
qDebug() << reExp3 << '\t'<< res3 << ":" << CalExp(res3.split(' ', QString::SkipEmptyParts));
qDebug() << reExp4 << '\t'<< res4 << ":" << CalExp(res4.split(' ', QString::SkipEmptyParts));
qDebug() << reExp5 << '\t'<< res5 << ":" << CalExp(res5.split(' ', QString::SkipEmptyParts));
}

二、一些小技巧

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

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

 //针对负号进行字符串修复 例如:-1*-3+2*(3+3) -> (0-1)*(0-3)+2*(3+3)
void repairExpress(QString & express)
{
bool repair = false;
int lpos = -, rpos = -;
QString result;
for(int i = ; i < express.size(); ++i)
{
QChar c = express[i];
if (c == '+' || c == '-' || c == '*' || c == '/')//出现符号时记录
{
if (repair)
{
result.append(')');
lpos = -;
repair = false;
} if (c == '-'&&
(i == || lpos != - && lpos == i - ))
{
result.append('(');
repair = true;
} lpos = i;
} result.append(c);
} express = result;
}

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

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

三、后缀表达式

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

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

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

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

下边我直接给出实现代码

 //中缀表达式转后缀表达式
QString change(const QString & s_mid)
{
QString result;
QStack<QChar> stk; QMap<QChar, int> op;//利用map来实现运算符对应其优先级
op['(']=;
op[')']=;
op['+']=;
op['-']=;
op['*']=;
op['/']=;
auto iter = s_mid.begin();
for(int i = ; i < s_mid.size(); ++i)
{
QChar c = s_mid[i];
if (c == ' ')
{
continue;
}
if (c == '-' &&
(i == || op.contains(s_mid[i-])))//可能为负号
{
result.append('');
}
if(op.contains(c))//判断该元素是否为运算符
{
if(c == ')')//情况2
{
while(stk.top() != '(')
{
rettifyExpress(result);
result.append(stk.top());
stk.pop();
}
stk.pop();
}
else if(stk.empty() || c == '(' || op[c] > op[stk.top()])//情况1、情况3
{
stk.push(c);
}
else if(op[c] <= op[stk.top()])//情况3
{
while(op[c] <= op[stk.top()] && (!stk.empty()))
{
rettifyExpress(result);
result.append(stk.top());
stk.pop();
if(stk.empty()) break;
}
stk.push(c);
} rettifyExpress(result);
}
else
{
result.append(c);
}
} while(stk.empty() == false)//当中缀表达式输出完成,所有元素出栈
{
rettifyExpress(result);
result.append(stk.top());
stk.pop();
} return result;
}

四、表达式计算

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

 //计算表达式值
double CalExp(const QStringList & express)
{
double result;
QStack<QString> stk;
for (int i = ; i < express.size(); ++i)
{
QString item = express[i];
if (item.size() == &&
(item.at() == "+" || item.at() == "-" || item.at() == "*" || item.at() == "/"))
{
double r = stk.pop().toDouble();
double l = stk.pop().toDouble();
switch(item.at().toLatin1())
{
case '+':
result = l + r;break;
case '-':
result = l - r;break;
case '*':
result = l * r;break;
case '/':
result = l / r;break;
} stk.push_back(QString::number(result));
}
else
{
stk.push_back(item);
}
} return result;
}

五、下载链接

  Qt之加减乘除四则运算-支持负数

参考文章:

1、四则运算表达式树 C++模板 支持括号和未知数

2、中缀表达式得到后缀表达式(c++、python实现)

Qt之加减乘除四则运算-支持负数的更多相关文章

  1. Qt国际化(Q_DECLARE_TR_FUNCTIONS() 宏给非Qt类添加翻译支持,以前没见过QTextEncoder和QTextDecoder和QLibraryInfo::location()和QEvent::LanguageChange)

    Internationalization with Qt 应用程序的国际化就是使得程序能在国际间可用而不仅仅是在本国可用的过程. Relevant Qt Classes andAPIs 以下的类支持Q ...

  2. python列表很聪明,支持负数索引

    python列表很聪明,支持负数索引

  3. Qt4学习笔记 (7) 本篇说一下Qt对于脚本的支持, 即QtScript模块.

    本篇说一下Qt对于脚本的支持, 即QtScript模块. Qt支持的脚本基于ECMAScript脚本语言, 这个东西又是javascript, jscript的基础. 所以, 一般只要学过javasc ...

  4. Python基础算法综合:加减乘除四则运算方法

    #!usr/bin/env python# -*- coding:utf-8 -*-#python的算法加减乘除用符号:+,-,*,/来表示#以下全是python2.x写法,3.x以上请在python ...

  5. Qt增加webp格式支持

    Webp 是一种图片文件格式,能在相同质量的情况下比 PNG 文件尺寸小巧. Chrome 应用商店图片已全部转换为 WebP 格式 YY(基于Qt开发)也已经把图片格式换成webp了 http:// ...

  6. Qt入门(9)——Qt中的线程支持

    Qt对线程提供了支持,基本形式有独立于平台的线程类.线程安全方式的事件传递和一个全局Qt库互斥量允许你可以从不同的线程调用Qt方法.警告:所有的GUI类(比如,QWidget和它的子类),操作系统核心 ...

  7. java实现超大整数加减乘除四则运算

    原理: 用数组存储数字,按照计算法则进行运算. 代码: package com.hdwang; import java.util.regex.Matcher; import java.util.reg ...

  8. poj 1348 Computing (四个数的加减乘除四则运算)

    http://poj.org/problem?id=1348 Computing Time Limit: 1000MS   Memory Limit: 10000K Total Submissions ...

  9. 用Java位运算实现加减乘除四则运算

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6412875.html 感谢博客:http://blog.csdn.net/itismelzp/article/ ...

随机推荐

  1. 使用 Babylon.js 在 HTML 页面加载 3D 对象

    五一 Windwos Blogs 推了一篇博客, Babylon.js v3.2 发布了.因为一直有想要在自己博客上加载 3D 对象的冲动,这两天正好看到了,就动手研究研究.本人之前也并没有接触过 W ...

  2. Windows下的OpenCVSharp配置

    OPenCvSharp是OpenCV的Net Warpper,应用最新的OpenCV库开发,目前放在github.. 本人认为OpenCvSharp比EmguCV使用起来更为方便,因为函数更接近于原生 ...

  3. JS跨域:1.解决方案之-SpringMVC拦截器

    一 拦截器代码 package com.wiimedia.controller; import java.util.List; import javax.servlet.http.HttpServle ...

  4. redis安装、使用

    官网:http://redis.io/ github地址:https://github.com/antirez/redis 简介:         redis是一个key-value存储系统.和Mem ...

  5. DevOps之一 Gitlab的安装与配置

    gitlab的安装 参考治疗:https://www.gitlab.com.cn/installation/#centos-7 http://www.21yunwei.com/archives/435 ...

  6. windows下安装mysql驱动mysql-python

    Windows下直接pip安装会出错 解决方案 到Python Extension Packages for Windows - Christoph Gohlke 下载MySQL_python‑1.2 ...

  7. 微信企业向用户银行卡付款API开发详解(PHP)

    最近在实现微信企业向用户银行卡付款时遇到了一些问题,发现官方文档说的太笼统,走了不少弯路,想要在此记录,希望可以帮到大家. 案例:企业付款到银行卡    微信接口链接:https://api.mch. ...

  8. pycharm linux版快捷方式创建

    ****************************pycharm_linux安装and快捷方式创建******************1.下载好安装包之后解压:    tar -xfz 压缩包名 ...

  9. Nctf_web_wp

    1.签到题     右键源代码即可2.md5 collision    这个考点是php"=="的弱相等,为何会出现弱加密呢,是因为在比较==两边的时候,会将字符串类型转化为相同, ...

  10. linux ulimit 调优

    概要:linux系统默认open files数目为1024, 有时应用程序会报Too many open files的错误,是因为open files 数目不够.这就需要修改ulimit和file-m ...