关闭

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

标签: Qt简单计算器实现中-后缀表达式转化方法
11006人阅读 评论(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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:146325次
    • 积分:2186
    • 等级:
    • 排名:第17870名
    • 原创:69篇
    • 转载:12篇
    • 译文:4篇
    • 评论:17条
    最新评论