QT之计算器对四则运算表达式的解析

前面我们已经关于计算器介绍的已经够多了,那么它现在还是没有具备计算的功能。

今天我们来继续讲解计算器的解析算法,那么对于一个四则运算表达式,
它是如何读懂的呢?比如:“+9.11 + ( -3 - 1 ) * -5 ”;

人类习惯的数学表达式叫做中缀表达式,还有一种将运算符放在数字后面的后缀表达式,
比如:5 + 3 ==> 5 3 +; 1 + 2 * 3 ==> 1 2 3 * +;像这种就是后缀表达式。

那么中缀表达式是符合人类的阅读和思维习惯,后缀表达式则符合计算机的运算方式,
这是一种消除了中缀表达式中的括号,同时保留中缀表达式中的运算优先级。
解决方案就是:
1、将中缀表达式进行数字和运算符的分离
2、将中缀表达式转换为后缀表达式
3、通过后缀表达式计算最终结果
所要计算的中缀表达式中包含
1、数字和小数点【0 - 9 或 . 】
2、符号位【 + 或 - 】
3、运算符【+,-,/, * 】
4、括号【 (或)】

具体的思想就是以符号作为标志对表达式中的字符逐个访问
1、定义累计变量 num
2、当前字符 exp[i] 为数字或小数点时:
累计:num += exp[i];
3、当前字符 exp[i] 为符号时:
num 为运算数,分离并保存;
若 exp[i] 为正负号:
累计符号位 + 和 - : num += exp[i];
若 exp[i] 为运算符:
分离并保存;

用伪代码描述出来就是这样:


我们接下来分析下这个分离算法的难点在哪?当然是如何区分正负号与加号和减号。我们可以这样想:正+ 和 负- 在表达式的第一个位置;括号后的 正+ 和 负- ;运算符后的 正+ 和 负-;

    具体代码则为:

QQueue<QString> QCalculatorDec::split(const QString& exp)
{
QQueue<QString> ret;
QString num = "";
QString pre = "";

for(int i=0; i<exp.length(); i++)
{
    if( isDigitOrDot(exp[i]) )  // 判断是否为数字0-9或小数点.
    {
        num += exp[i];
        pre = exp[i];
    }
    else if( isSymbol(exp[i]) ) // 如果是符号
    {
        if( !num.isEmpty() )    // 数组不为空
        {
            ret.enqueue(num);

            num.clear();
        }

        if( isSign(exp[i]) && ((pre == "") || (pre == "(") || isOperator(pre)) )    // 如果是正负号或者()或操作符
        {
            num += exp[i];
        }
        else
        {
            ret.enqueue(exp[i]);
        }

        pre = exp[i];
    }
}

if( !num.isEmpty() )
{
    ret.enqueue(num);
}

return ret;

}

我们在构造函数里设置如下:


那么我们构建运行完得到的结果如下:

那么我们可以看到计算器正确的识别了四则表达式,今天我们就先学习到这了。后面我们接着继续计算器的解析算法的学习。

以上内容来自狄泰软件学院的QT教程,欢迎大家一起来学习,可以加我QQ:243343083,一起学习。狄泰技术交流群:199546072

原文地址:http://blog.51cto.com/12810168/2088766

时间: 2024-08-10 16:13:32

QT之计算器对四则运算表达式的解析的相关文章

四则运算表达式解析和求值(支持括号、小数、小数正负号)

需求分析 四则运算表达式的解析和求值从概念上看是一个逻辑很清晰的过程. 遵循了左结合.优先级差异和括号可以提升优先级这三条规则. 实现思路 实际上只要遍历表达式,将小数和运算符分离到两个序列容器中,在遍历的过程中,考虑左结合和括号对优先级的影响,将相关信息和运算符记录在一起,然后在遍历结束后,按照优先顺序从高到底,从小数序列中拉取两个元素(可能是中间结果的二叉树,实际上小数是一种特例,是左右子树为空的解析完成的二叉树),并且把运算符的两棵子树指向两个元素,把这棵新树放回到小数容器中.不断重复这个

QT之计算器核心解析算法

上节我们说到计算机默认的是后缀表达式,那么中缀表达式转后缀表达式的过程就类似于编译过程. 必须得注意这么几个问题:四则运算表达式中的括号必须匹配:根据运算符优先级进行转换:转换后的表达式中没有括号:转换后可以顺序计算出最终结果.下来我们就讲下具体的转换过程:1.当前元素 e 为数字:输出2.当前元素 e 为运算符时:1. 与栈顶运算符进行优先级比较:2.小于等于时将栈顶元素输出,转1:3.大于时将当前元素 e 入栈3.当前元素 e 为左括号:入栈4.当前元素 e 为右括号:1.弹出栈顶元素并输出

四则运算表达式求值 OpenJ_Bailian - 4132

四则运算表达式求值 OpenJ_Bailian - 4132 题意:设计一个计算器,实现+-*/以及()的表达式运算求值. 栈的应用,这学期学数据结构,手写了栈练一下~ 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=10010; //最大表达式长度 4 5 template <typename T> 6 class Stack; 7 8 template <typename T> 9

程序输出小学四则运算表达式,支持真分数四则运算

程序设计思路: 1.运算式的输出格式可以为 数字 运算符 数字,也可以为 数字 运算符 数字 运算符 数字,还可以是更复杂的式子,在此只实现了2-3个数字的运算式. 2.将式子分为两类,第一类为20个,第二类为10个,分别用FOR循环控制输出. 3.第一类式子稍简单,只需通过随机函数将两个数字赋值,中间运算符通过数组下标的随机赋值实现随机性,再通过格式输出即可 4.此时还要考虑运算符为 ‘/’,并且除数为0的情况,这时用if语句设置条件排除即可 5.计算第一类式子结果可以参考计算器的功能代码,用

C++实现对数学基本运算表达式的解析

代码地址如下:<br>http://www.demodashi.com/demo/11078.html 前段时间在LeetCode上刷题,遇到了很多涉及对字符串进行解析的题目.可能是出于这个原因,最近迷恋上了字符串的解析问题.数学基本运算表达式的解析就涉及这类问题.所谓数学基本运算表达式的解析就是指给定一个表达式字符串,如1 + 1,3 * 9,对这个字符串进行解析,从而得到这个表达式的运算结果.(数学基本运算表达式也就是只用加减乘除进行计算的数学表达式) 其实站在我的角度来看,我觉得对数学基

四则运算表达式求值の各种心碎

实验三---四则运算表达式求值 一.基本要求: ( 1 ) 利用二叉树后序遍历来实现表达式的转换,同时可以使用实验三的结果来求解后缀表达式的值. ( 2) 输入输出格式: 输入格式:在字符界面上输入一个中缀表达式,回车表示结束. 请输入表达式: 输入一个中缀表达式 输出格式:如果该中缀表达式正确,那么在字符界面上输出其后缀表达式,其中后 缀表达式中两相邻操作数之间利用空格隔开:如果不正确,在字符界面上输出表达式错误提示. 逆波兰表达式为: 输出逆波兰表达式 运算结果为:输出运算后的结果 测试数据

计算四则运算表达式(Java语言实现)

计算四则运算表达式主要是分两步运算  第一步是把 中缀表达式 转换成 后缀表达式.参考大一下期学的 <数据结构与算法分析--C语言描述>3.3.3 教材,完成下列代码: static String mid_to_suf(String str){ Stack<Character> s = new Stack<Character>(); String suf = new String(); HashMap<Character, Integer> map = ne

模拟计算器进行四则运算(同等优先级)(第2届第3题)

题目要求 问题描述:模拟计算器进行四则运算.假设只有+.-.*./.=五种运算符,且它们优先级相等.输入=后会显示计算结果. 样例输入:8.5+0.5*2.5= 样例输出:22.5 解决方案 比起需要考虑优先级,且有多种运算符的题目,这个问题显然要简单地多,直接读取输入并进行分析,然后再计算即可. 源码示例 结果展示 小结 题目虽简单,但是还要考虑细节,比如第一个数为负数的情况.另外本示范代码未对异常输入做检查,所以如果是写严谨的程序,为了保证健壮性,必须进行细致的错误检查.

数据结构(7)----栈与队列之栈的应用四则运算表达式求值

栈与队列之栈的应用四则运算表达式求值 栈在四则运算表达式求值的应用为逆波兰表达式(后缀表达式) 普通算式(中缀表达式):9 + (3 - 1) * 3 + 10 / 2     ---(1) 逆波兰表达式(后缀表达式):9 3 1 - 3 * + 10 2 /         ---(2) 1:逆波兰表达式的计算规则 从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到符号,就将处于栈顶的两个数字出栈,进行运算,再把运算结果进栈,一直到最终获得结果.接下来我们以(2)式为例: