Qt之加减乘除四则运算-支持负数
一、效果展示
如图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之加减乘除四则运算-支持负数的更多相关文章
- Qt国际化(Q_DECLARE_TR_FUNCTIONS() 宏给非Qt类添加翻译支持,以前没见过QTextEncoder和QTextDecoder和QLibraryInfo::location()和QEvent::LanguageChange)
Internationalization with Qt 应用程序的国际化就是使得程序能在国际间可用而不仅仅是在本国可用的过程. Relevant Qt Classes andAPIs 以下的类支持Q ...
- python列表很聪明,支持负数索引
python列表很聪明,支持负数索引
- Qt4学习笔记 (7) 本篇说一下Qt对于脚本的支持, 即QtScript模块.
本篇说一下Qt对于脚本的支持, 即QtScript模块. Qt支持的脚本基于ECMAScript脚本语言, 这个东西又是javascript, jscript的基础. 所以, 一般只要学过javasc ...
- Python基础算法综合:加减乘除四则运算方法
#!usr/bin/env python# -*- coding:utf-8 -*-#python的算法加减乘除用符号:+,-,*,/来表示#以下全是python2.x写法,3.x以上请在python ...
- Qt增加webp格式支持
Webp 是一种图片文件格式,能在相同质量的情况下比 PNG 文件尺寸小巧. Chrome 应用商店图片已全部转换为 WebP 格式 YY(基于Qt开发)也已经把图片格式换成webp了 http:// ...
- Qt入门(9)——Qt中的线程支持
Qt对线程提供了支持,基本形式有独立于平台的线程类.线程安全方式的事件传递和一个全局Qt库互斥量允许你可以从不同的线程调用Qt方法.警告:所有的GUI类(比如,QWidget和它的子类),操作系统核心 ...
- java实现超大整数加减乘除四则运算
原理: 用数组存储数字,按照计算法则进行运算. 代码: package com.hdwang; import java.util.regex.Matcher; import java.util.reg ...
- poj 1348 Computing (四个数的加减乘除四则运算)
http://poj.org/problem?id=1348 Computing Time Limit: 1000MS Memory Limit: 10000K Total Submissions ...
- 用Java位运算实现加减乘除四则运算
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6412875.html 感谢博客:http://blog.csdn.net/itismelzp/article/ ...
随机推荐
- Ubuntu 18.04 启动root账号并授权远程登录
Ubuntu 18.04 刚刚上市2个月,下载安装,尝尝鲜~ 安装界面看上去舒服许多, 安装的速度也较之前17.04 和16.04 都快了许多.抱歉,未截图. Ubuntu 安装完成后默认不启动roo ...
- 修改input获取焦点背景黄色
input:-webkit-autofill { -webkit-box-shadow: 0 0 0px 1000px white inset !important; }
- Mysql 查询条件中字符串尾部有空格也能匹配上的问题
一.表结构 TABLE person id name 1 你 2 你(一个空格) 3 你(二个空格) 二.查询与结果 select * from person where `name` = ? 无论 ...
- 【转】IE浏览器快捷键大全
一般快捷键F11打开/关闭全屏模式 TAB循环的选择地址栏,刷新键和当前标签页 CTRL+F在当前标签页查询字或短语 CTRL+N为当前标签页打开一个新窗口 CTRL+P打印当前标签页 CTRL+A选 ...
- Django中数据库表的关联与创建(语言:python)
首先选择选用的数据库,(本人选用django(1.11.8版本)) 在主项目settings中操作如下: DATABASES = { 'default': { 'ENGINE': 'django.db ...
- CXF整合spring
近公司需要弄webservics,还说不用框架整合(提倡使用hessian,他们既然说与操作系统有兼容问题,由于人员单薄,不得不屈服,哎),我想了老半天没弄明白他说的不用框架整合spring,尝试过直 ...
- PAT1127:ZigZagging on a Tree
1127. ZigZagging on a Tree (30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...
- 如何开始使用 Java 机器学习
开始Java机器学习的最好工具是什么? 这个问题已经有一段时间了,但最近这些日子几乎每个人都在谈论人工智能和机器学习.这已经不再是一个保留给科学家和研究者的秘密,而是几乎实现于每一项新兴技术中. 在下 ...
- elementui左侧菜单栏刷新后还是原来的状态
<template> <div id="leftMenuList"> <el-row> <el-col :span="24&qu ...
- 系列博文-LowPoly风格的图像生成器
https://github.com/Ovilia/Polyvia http://www.zhihu.com/question/29856775/answer/57668656 http://zhan ...