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/ ...
随机推荐
- C# SqlBulkCopy数据批量入库
准备条件:20万+数据 界面设计使用的WPF. 没有对比就没有伤害,以下是我两种方式导入数据案例. 运行 结果对比: 首先使用一般sql语句导入,因为时间原因,我就没有等待程序执行完,但是我记录了大约 ...
- CSS学习笔记1:基础知识
CSS规则由两部分组成,选择器和声明 选择器:标签,告诉浏览器哪些标签需要用到这个样式 声明:样式的内容,由一或多对属性:值以:隔开组成,由{}包围,需要多个选择器时以逗号隔开 ...
- MySQL中的外键约束
- javascript 用函数语句和表达式定义函数的区别详解
通常我们会看到以下两种定义函数的方式: // 函数语句 function fn(str) { console.log(str); }; // 表达式定义 var fnx=function(str) { ...
- android获取手机机型、厂商、deviceID基本信息
/** * 系统工具类 */ public class SystemUtil { /** * 获取当前手机系统语言. * * @return 返回当前系统语言.例如:当前设置的是"中文-中国 ...
- JavaScript和JQuery的区别
一.本质上的区别 1.JavaScript 是通过<script></script>标签插入到HTML页面,可由所有的现代浏览器执行的一种轻量级的编程语言. 2.JQuery是 ...
- 易用性测试、本地化测试、部署测试、无障碍测试、回归测试、冒烟测试、A/B测试
1.易用性定义: 易用性测试是指测试用户使用软件时是否感觉方便,是否能保证用户使用的测试类型2.本地化测试: ·定义:针对软件的本地化版本实施的针对性测试 ·测试内容: (1)语言,书写习惯 (2)时 ...
- linux timerfd系列函数总结
网上关于timerfd的文章很多,在这儿归纳总结一下方便以后使用,顺便贴出一个timerfd配合epoll使用的简单例子 一.timerfd系列函数 timerfd是Linux为用户程序提供的一个定时 ...
- 0517JS综合练习、挂事件练习
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> ...
- DOS系统常用命令
前言: DOS命令是DOS操作系统使用的命令.DOS操作系统是一种磁盘操作系统,从Windows95.98到今天的Windows10都内置有DOS操作系统.可以通过"win+R", ...