关闭

Qt实现的简单计算器-计算简单表达式

标签: Qt简单计算器实现中-后缀表达式转化方法
11992人阅读 评论(4) 收藏 举报
分类:

    此程序是在学习Qt的时候写的,Qt入门简单,了解布局之后能迅速实现自己想要的界面,布局是比较简单的部分,不写。算法可能是多数人包括我自己比较薄弱的地方,因此在这里做主要介绍。 学过编译原理或者离散数学的话可能知道后缀表达式。后缀表达式是运算符写在操作数后边不包扩括号的算数表达式,也叫逆波兰表达式。中缀表达式对人来说很好理解,但是对于计算机来说就很困难,在中缀表达式的情况下求值,既要考虑括号,优先级,还要考虑操作符出现的先后顺序,但是后缀表达式就不同,后缀表达式的运算符是按照一定的顺序出现的,所以不不许要加括号来决定优先级的高低,一次遍历就可以完成计算,相比中缀表达式,算法的复杂度要降低很多。

中缀表达式->后缀表达式

转换方法:

  • 1. 首先将这个中缀表达式的所有运算加括号 ((a+(b*c))-(d+e))
  • 2. 然后将所有运算符放到相应括号的后面,变成了 ((a(bc)*)+(de)+)-
  • 3. 最后把所有括号去掉,得到的结果就是后缀表达式:abc*+de+-

另一种方法:

  • 将中缀表达式中的操作数看成叶子节点,将所有的操作符表示成内节点,画出该二叉树。
  • 对该二叉树按照前序|中序|后序的遍历方式遍历就可以得到相应的表达式。

编程实现方法

利用堆栈来做临时的运算符存取场所:

例如:1+2*3-(4+5)*6                                后缀表达式为:123*+45+6*-

现在用字符数组mid存储中缀表达式,用end存储后缀表达式,堆栈为mystack来模拟下过程:

序号                             中缀表达式mid                 堆栈操作                  堆栈mystack                           后缀表达式end

   0                                 1+2*3-(4+5)*6                 无                             空                                              空

   1                                 +2*3-(4+5)*6                    无                             空                                              1

   2                                 2*3-(4+5)*6                     push                          +                                               1

   3                                 *3-(4+5)*6                              无                              +                                              12                    

   4                                 3-(4+5)*6                              push                          *+                                             12

   5                                  -(4+5)*6                                 无                             *+                                             123

   6                                 (4+5)*6                            <-pop <-pop push             -                                           123*+

   7                                 4+5)*6                                    push                         (-                                              123*+

   8                                 +5)*6                                       无                              (-                                             123*+4

   9                                  5)*6                                         push                       +(-                                            123*+4

   10                                )*6                                            无                            +(-                                           123*+45

   11                                *6                                            <-pop pop                -                                              123*+45+

   12                               6                                               push                        *-                                             123*+45+

   13                               空                                             无                             *-                                             123*+45+6            

   14                               空                                        <-pop <-pop                 空                                           123*+45+6*-             //  扫描结束,将所有的操作符出栈

声明:<-pop表示弹出的数据存入end中,pop仅仅弹出数据不存人end.                   

函数原型:

//中缀表达式转为后缀表达式的实现
void calculator::mid2end(const char* mid,char* end){
 int i=0;
 int j=0;
while(mid[i]){
    if(mid[i] == '.'||mid[i] == '%')continue;
    //mystack.push('#');
        //遇到数字直接存入end,
        if(mid[i]>='0'&&mid[i]<='9'){
                end[j++] = mid[i];

        }else if(mid[i]=='-'||mid[i]=='+'){
                //加号和减号的操作
            if(!mystack.isEmpty()){
                while((!mystack.isEmpty()) && (mystack.top()=='+'||mystack.top()=='-'||mystack.top()=='*'||mystack.top()=='/')){
                //只要是优先级不小于+-的运算符
                end[j++]=mystack.pop();
                }
                }
                mystack.push(mid[i]);

        }else if(mid[i]=='*'||mid[i]=='/'){
            if(!mystack.isEmpty()){
        while((!mystack.isEmpty()) && (mystack.top()=='*'||mystack.top()=='/')){
                end[j++]=mystack.pop();
        }
    }
                mystack.push(mid[i]);

        }else if('('==mid[i]){
        mystack.push(mid[i]);
        }else if(')'==mid[i]){
        //遇到)将(之前的所有数据输出之后将(出栈
            if(!mystack.isEmpty()){
        while((!mystack.isEmpty()) && mystack.top()!='('){
        end[j++]=mystack.pop();
        }
        }//当前的)直接输出
        mystack.pop();
        }
i++;
}
//扫描结束将所有的操作符出栈
while(!mystack.isEmpty())end[j++]=mystack.pop();
}


同样利用堆栈计算后缀表达式的和:

int calculator::calculate(const char* end){
        int i=0;
        int a;
        int b;
        while(end[i])
        {
                switch(end[i]){
                        case '+':
                                b = mystack.pop();
                                a = mystack.pop();
                                mystack.push(a+b);
                                qDebug()<<a<<"+"<<b<<"="<<mystack.top()<<endl;
                                break;
                        case '-':
                                b = mystack.pop();
                                a = mystack.pop();
                                mystack.push(a-b);
                                qDebug()<<a<<"-"<<b<<"="<<mystack.top()<<endl;
                                break;
                        case '*':
                                b = mystack.pop();
                                a = mystack.pop();
                                mystack.push(a*b);
                                qDebug()<<a<<"*"<<b<<"="<<mystack.top()<<endl;
                                break;
                        case '/':
                                b = mystack.pop();
                                a = mystack.pop();
                                mystack.push(a/b);
                                qDebug()<<a<<"/"<<b<<"="<<mystack.top()<<endl;
                                break;
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                        case '8':
                        case '9':
                                mystack.push(end[i]-'0');//ASCII码 ‘8’ - ‘0’ == 8;
                }
                i++;
        }
        return mystack.top();
}


界面:

源代码上传到我的空间   [表达式计算器],还有许多处不足,需要限制用户的操作。

若您有更好的关于表达式的计算方法请留言。






1
0
查看评论

Qt简易计算器的代码实现

敲了一个简易计算器的代码,代码不难,但要考虑的也挺多的!   我这个计算器,除法的功能只能是整除,不能实现结果是小数的功能   如果有高手指导,望指点!      calculator.h的代码 #ifndef CALCULATOR_H #defin...
  • zycxnanwang
  • zycxnanwang
  • 2016-05-26 10:38
  • 13740

Qt实现简单计算器

Qt5.8实现计算器
  • tiantianfendou
  • tiantianfendou
  • 2017-03-24 15:03
  • 3140

QT学习之路之计算器开发

前几天老师简单的讲解了下QT的信号与槽,并且实现了一个简单的计算机加法,如下图: 我根据对老师所讲类容的理解以及一些资料的查找自己做了一个简单的计算器。 1 首先上个界面,页面布局用Grid Layout。 2 建立各种槽,代码如下: mainwindow.h文件代码: ...
  • x13308605592
  • x13308605592
  • 2016-04-15 15:16
  • 840

Qt5 科学计算器的实现

  • 2015-12-13 09:40
  • 25KB
  • 下载

QT实现简单计算器

  • 2016-01-15 16:23
  • 1.34MB
  • 下载

用Qt实现的计算器

需求分析模块图类图核心算法中缀表达式转化为后缀表达式规则:从左到右遍历中缀表达式(表达式运算符在两数字之间,比如(2+1)3)的每个数字和符号,若是数字就输出,即成为后缀表达式(表达式运算符在数字之后,不包含括号,比如2 1+3 )的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于...
  • jiaxingzheng
  • jiaxingzheng
  • 2015-03-13 13:43
  • 1324

QT实现的计算器

  • 2014-01-03 12:56
  • 264KB
  • 下载

QT实现一个简单的计算器

首先先看下这个程序的运行的demo,效果图如下: 在这个小程序中,有些值得注意的东西,就是包含如下: 1.文本编辑框 2.一系列的控件 在上面的控件类Button都是继承自QToolButton类,并重写了其中的sizeHint()函数,让宽度拉升 具体代码...
  • u011619422
  • u011619422
  • 2015-08-05 10:44
  • 5339

QT实现一个简单的计算器

最近几天在学习QT,在了解了信号和槽机制、布局管理、还有一些控件的使用后,便试着写了一个计算器,带自定义的快捷键,剪贴板(复制和粘贴)的操作,有 菜单栏->选择 里的功能还未实现,等啥时候有时间把它补上吧。还有许多不足和需要修改的地方,希望各位大牛能帮忙指出其中的问题,谢谢。 下面就贴出我的...
  • a1069962325
  • a1069962325
  • 2015-07-26 12:35
  • 7466

我的博客第一发--qt实现科学计算器

首先提一下,这是我大一暑假独立完成的c++课程设计的作业,由于是用qt做的,而且我并没有将它release,因此只能提供一下源代码供大家下载,如需运行的话需要自己用qt4编译,或者添加必要的dll 我先将链接贴出来吧。
  • eligah_
  • eligah_
  • 2015-09-18 19:38
  • 2652
    个人资料
    • 访问:165016次
    • 积分:2428
    • 等级:
    • 排名:第17975名
    • 原创:69篇
    • 转载:12篇
    • 译文:4篇
    • 评论:17条
    最新评论