用Qt完成一个计算器


前言

提示:Qt5.9.8 MinGW 32bit


一、项目分析

根据不同符号的算数优先级,先将输入的式子从中缀表达式转为后缀表达式,此时运算顺序已经排列完毕。
示例:
Exp=ab+(c-d/e)f
postExp=ab
cde/-f*+*
算法思想:https://www.cnblogs.com/lifexy/p/8901369.html
之后使用一个栈,如若是数字则压栈,否则弹出栈中的两个数,与符号做运算。

二、完成步骤

1.Ui设计以及命名

2.代码实现

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    QString result;//保存结果
    QString hold;//保存记录
    int priority(QChar p);//设置运算符优先级
    void resolve();//取得后缀表达式result
    QString solution();//求解
    QString calculation(double val1,double val2,QChar op);//两个数的运算
    int digit(int val);

    ~Widget();
public slots:
    void add(QString temp);//用于从按键添加符号,和更新poly
private:
    Ui::Widget *ui;
    QString poly;//保存多项式

};

#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
#include "ui_widget.h"
#include<QPushButton>
#include<QStack>
#include<QDebug>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("Calculator");
    //数字
    connect(ui->pushButton_0,&QPushButton::clicked,[this](){add("0");});
    connect(ui->pushButton_1,&QPushButton::clicked,[this](){add("1");});
    connect(ui->pushButton_2,&QPushButton::clicked,[this](){add("2");});
    connect(ui->pushButton_3,&QPushButton::clicked,[this](){add("3");});
    connect(ui->pushButton_4,&QPushButton::clicked,[this](){add("4");});
    connect(ui->pushButton_5,&QPushButton::clicked,[this](){add("5");});
    connect(ui->pushButton_6,&QPushButton::clicked,[this](){add("6");});
    connect(ui->pushButton_7,&QPushButton::clicked,[this](){add("7");});
    connect(ui->pushButton_8,&QPushButton::clicked,[this](){add("8");});
    connect(ui->pushButton_9,&QPushButton::clicked,[this](){add("9");});
    //括号
    connect(ui->pushButton_11,&QPushButton::clicked,[this](){add("(");});
    connect(ui->pushButton_10,&QPushButton::clicked,[this](){add(")");});

    //符号
    connect(ui->pushButton_add,&QPushButton::clicked,[this](){add("+");});
    connect(ui->pushButton_sub,&QPushButton::clicked,[this](){add("-");});
    connect(ui->pushButton_mul,&QPushButton::clicked,[this](){add("*");});
    connect(ui->pushButton_div,&QPushButton::clicked,[this](){add("/");});
    connect(ui->pushButton_sur,&QPushButton::clicked,[this](){add("%");});
    connect(ui->pushButton_dot,&QPushButton::clicked,[this](){add(".");});

    //退格
    connect(ui->pushButton_B,&QPushButton::clicked,[this](){
        poly.remove(poly.length()-1,1);
        ui->lineEdit->setText(poly);
    });

    //清空
    connect(ui->pushButton_C,&QPushButton::clicked,[this](){
        poly.clear();
        ui->lineEdit->setText(poly);
    });

    //CE
    connect(ui->pushButton_CE,&QPushButton::clicked,[this](){
        while((!poly.isEmpty()) && priority(poly[poly.length()-1]) == 0){
            poly.remove(poly.length()-1,1);
            ui->lineEdit->setText(poly);
        }
    });

    //等号
    connect(ui->pushButton_equ,&QPushButton::clicked,[this](){
        add("=");
        //lineEdit_2用于保存记录
        ui->lineEdit_2->setText(hold += poly);

        poly = solution();

        result.clear();

        ui->lineEdit->setText(poly);

        ui->lineEdit_2->setText(hold = hold + poly + ";" );
    });

}

Widget::~Widget()
{
    delete ui;
}
void Widget::add(QString temp){
    poly += temp;
    ui->lineEdit->setText(poly);
}
int Widget::priority(QChar p)
{//优先级的判断
    if(p=="+"){
        return 1;
    }
    if(p=="-"){
        return 1;
    }
    if(p=="*"){
        return 2;
    }
    if(p=="/"){
        return 2;
    }
    if(p=="%"){
        return 2;
    }
    if(p=="/0"){
        return 3;
    }
    if(p==")"){
        return 4;
    }
    return 0;
}

void Widget::resolve(){
    QStack<QChar> ret;
    for(int i=0;i < poly.length();i++){
        if(poly[i] == "(")
        {//如果是"("直接入栈
            ret.push(poly[i]);
            if(poly[(++i)--] == "-")
            {
                result.push_back("0 ");
            }
            continue;
        }
        if(priority(poly[i]) == 4)
        {//如果遇到了右括号,则直到遇到左括号位置,将栈中元素全部出栈到result
            while(ret.top() != "("){
                result.push_back(ret.pop());
            }
            if(ret.top() == "("){
                ret.pop();
            }
            continue;
        }
        if(ret.isEmpty() && (priority(poly[i]) != 0))
        {//如果栈为空,且为符号,则入栈
            if((poly[i] == "-") && (result.isEmpty()))
            {//负数补0
                result.push_back("0 ");
            }
            ret.push(poly[i]);
            continue;
        }
        if((!ret.isEmpty()) && (priority(poly[i]) != 0) && (priority(ret.top()) < priority(poly[i])) && poly[i] != ")")
        {//如果字符串中的优先级大于,栈中字符的优先级,则入栈
            ret.push(poly[i]);
            continue;
        }
        if((!ret.isEmpty()) && (priority(poly[i]) != 0) && (priority(ret.top()) >= priority(poly[i])))
        {//如果小于等于,则出栈,入result
            result.push_back(ret.pop());
            while ((!ret.isEmpty()) && (priority(ret.top()) >= priority(poly[i]))) {
                result.push_back(ret.pop());
            }
            ret.push(poly[i]);
            continue;
        }
        if(poly[i] == "=")
        {//poly结束后,将栈中元素全部弹出到result,并结束循环
            int j=ret.length();
            for(int i=0;i < j;i++){
                result.push_back(ret.pop());
            }
            break;
        }
        if((poly[i] != ")") && (priority(poly[i]) == 0))
        {//如果是数字,则直接入result
            result.push_back(poly[i]);
            while((priority(poly[++i]) == 0) && poly[i] != "="){
                result.push_back(poly[i]);
            }
            result.push_back(" ");
            --i;
            continue;
        }
    }
}
QString Widget::solution(){
    resolve();
    QStack<QChar> ret;
    for(int i=0;i<result.length();i++){
        if(priority(result[i]) == 0){
            while(result[i] != " "){
                ret.push(result[i]);
                i++;
            }
            ret.push(result[i]);
            continue;
        }
        if(priority(result[i]) != 0){
            double val1;
            double val2;
            if(ret.top() == " "){
                ret.pop();
            }
            val1 = ret.pop().digitValue();
            while((ret.length() != 0) && (ret.top() != " "))
            {//得到第一个数
                if(ret.top() == "-")
                {//负数判断
                    val1 = 0 - val1;
                    ret.pop();
                    continue;
                }
                if(ret.top() == ".")
                {
                    //如果是有小数的话
                    ret.pop();
                    int n = digit(val1);
                    val1 = val1/n;
                    val1 += ret.pop().digitValue();
                    continue;
                }
                if(ret.top() == "0"){
                    int n = digit(val1);
                    val1 += 10 * n;
                    ret.pop();
                    while(ret.top() == "0")
                    {
                        val1 *= 10;
                        ret.pop();
                    }
                    val1 *= (ret.pop().digitValue());
                    continue;
                }
                if(ret.top() != "0"){
                    int n = digit(val1);
                    val1 += (ret.pop().digitValue())*n;
                }
            }
            if(ret.top() == " "){
                ret.pop();
            }
            val2 = ret.pop().digitValue();
            while((!ret.isEmpty()) && (ret.top() != " "))
            {//得到第二个数
                if(ret.top() == "-")
                {//负数判断
                    val2 = 0 - val2;
                    ret.pop();
                    continue;
                }
                if(ret.top() == ".")
                {//如果有小数的话
                    ret.pop();
                    int n = digit(val2);
                    val2 = val2/n;
                    val2 += ret.pop().digitValue();
                    continue;
                }

                if(ret.top() == "0"){
                    int n = digit(val2);
                    val2 += 10 * n;
                    ret.pop();
                    while(ret.top() == "0")
                    {
                        val2 *= 10;
                        ret.pop();
                    }
                    val2 *= (ret.pop().digitValue());
                    continue;
                }
                if(ret.top() != "0"){
                    int n = digit(val2);
                    val2 += (ret.pop().digitValue())*n;
                }
            }
            //计算
            QString val = calculation(val1,val2,result[i]);
            for (int i = 0;i < val.length();i++)
            {//把值入栈
                ret.push(val[i]);
            }
            ret.push(' ');
            continue;
        }
    }
    result.clear();
    if(ret.top() == " "){
        ret.pop();
    }
    while(!ret.isEmpty()){
        //使用头插
        result.push_front(ret.pop());
    }
    return result;
}
QString Widget::calculation(double val1,double val2,QChar op)
{//用于两个数的计算
    char p=op.toLatin1();
    QString tra;
    switch(p){
    case '+':
        return tra=QString::number(val2+val1);
    case '-':
        return tra=QString::number(val2-val1);
    case '*':
        return tra=QString::number(val2*val1);
    case '%':
    {
        double val = fmod(val2,val1);//利用double类型的取余函数
        return tra=QString::number(val);
    }
    case '/':
    default:
        return tra=QString::number(val2/val1);
    }
}
int Widget::digit(int temp){
    if(temp == 0){
        return 10;
    }
    int t = 1;
    while(temp != 0){
        temp = temp/10;
        t *= 10;
    }
    return t;
}

main.cpp:

#include "Widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}


总结

提示:
链接:https://pan.baidu.com/s/1mXnJ3yu_evF5GPtXy4whoA
提取码:hnwm
以上是Windows下可执行文件的获取方式
源码:
链接:https://pan.baidu.com/s/1VJRIWL0BNcCqLm7fFm7mBw
提取码:cixl

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值