您的位置:首页 > 编程语言 > Qt开发

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

2013-12-03 20:15 225 查看
此程序是在学习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();
}


界面:



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

若您有更好的关于表达式的计算方法请留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: