QT计算器

程序综合设计实践 :用QT实现简易计算器及贷款计算

1,项目概述

该项目目标是设计开发一个支持连续计算的包括括号( ),求余%四则运算+ - * /的计算器 Calculator 以及贷款计算功能 Mortgage
本程序为本人初学一周QT所作,才疏学亦浅,程序中绝对有意想不到的蜜汁bug😆(逃)欢迎大家评论区交流丫。
项目下载地址

avatar avatar

通过单击按钮,输入并完成如4+5.21+65*(8+16)-2 类似的连续计算,并将运算结果显示在输出文本框 lineEdit 中,计算的式子移至上方的 label 中。
支持负数,小数运算,并且精度为小数点后位。支持简单的错误性检验。 CE 清空 Del 后退 More 切换至贷款计算。两个界面,贷款计算界面不做过多赘述。

2,设计步骤 (以下只举例 Calculator 界面)

###界面设计部分
界面设计部分如图由

label (显示计算的式子)
lineedit (显示结果或者当前输入的式子)
以及各个按钮组成。

创建按钮的时候因为数目有点多,所以我们可以用数组保存创建的按钮 指针 ,后面就可以直接用 索引 对按钮进行操控。

QT支持用 css 渲染元素。如label->setStyleSheet("font-size:12px;color:grey;border-bottom:1px solid #f1f1f1;border-radius:5px;text-align:right;");


    //from widget.cpp

    setFixedSize(400,450);  //固定窗口大小
    setWindowIcon(QIcon(":/icon.png")); //设置icon

    QLineEdit* lineedit = new QLineEdit(this);      //创建 lineedit 对象
    lineedit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);    //将该对象设为宽高可扩展
    QLabel* label = new QLabel(this);
    label->setText("请在下方输入要计算的式子...");  //设置文本内容
    QString btnstr[22] = {"(", ")", "%", "CE", "Del",
                        "7", "8", "9", "+", "-",
                        "4", "5", "6", "*", "/",
                        "1", "2", "3", "More", "=",
                        "0", "."
                       };                       
    auto that = this;
    QPushButton* btn[22];   //创建22个按钮并用数组储存,并且绑定相应的槽函数。方便后面布局(偷懒
    for(int i=0; i<22; i++){
        btn[i] = new QPushButton(that);
        btn[i]->setText(btnstr[i]);
        btn[i]->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        connect(btn[i],&QPushButton::clicked,that,[=](){
            that->input(btnstr[i], lineedit, label);
        });
    }
    
    //设置样式,美化
    btn[4]->setStyleSheet("color:red;");
    btn[18]->setStyleSheet("color:yellow;");
    int cyellow[9] = {0,1,2,3,8,9,13,14};
    for(int i=0; i<9; i++)  btn[cyellow[i]]->setStyleSheet("color:#38d6d5;");
    lineedit->setStyleSheet("color:#333;font-size:21px;font-weight:bolder;border:1px dashed #f1f1f1;border-radius:5px;text-align:right;");
    label->setStyleSheet("font-size:12px;color:grey;border-bottom:1px solid #f1f1f1;border-radius:5px;text-align:right;");
    lineedit->setAlignment( Qt::AlignRight);
    label->setAlignment( Qt::AlignRight);
    setStyleSheet("QPushButton {font-size:20px;font-weight:bold;color:ligrhtgrey;background-color: rgba(255, 255, 255, 0%);border:1px solid grey;border-radius:5px;} QPushButton:hover, QLabel:hover {font-size:25px;} Widget {background:qlineargradient(spread:pad,y1:1,y2:0,stop:0 #79f4f3,stop:1 #f8fefe);}");
    setWindowTitle("Calculator");
    
    //设置布局
    QGridLayout* computelayout = new QGridLayout(this);
    computelayout->addWidget(label, 0, 0, 1, 5);
    computelayout->addWidget(lineedit, 1, 0, 1, 5);
    computelayout->addWidget(btn[0], 2, 0, 1, 1);
    computelayout->addWidget(btn[1], 2, 1, 1, 1);
    computelayout->addWidget(btn[2], 2, 2, 1, 1);
    computelayout->addWidget(btn[3], 2, 3, 1, 1);
    computelayout->addWidget(btn[4], 2, 4, 1, 1);
    computelayout->addWidget(btn[5], 3, 0, 1, 1);
    computelayout->addWidget(btn[6], 3, 1, 1, 1);
    computelayout->addWidget(btn[7], 3, 2, 1, 1);
    computelayout->addWidget(btn[8], 3, 3, 1, 1);
    computelayout->addWidget(btn[9], 3, 4, 1, 1);
    computelayout->addWidget(btn[10], 4, 0, 1, 1);
    computelayout->addWidget(btn[11], 4, 1, 1, 1);
    computelayout->addWidget(btn[12], 4, 2, 1, 1);
    computelayout->addWidget(btn[13], 4, 3, 1, 1);
    computelayout->addWidget(btn[14], 4, 4, 1, 1);
    computelayout->addWidget(btn[15], 5, 0, 1, 1);
    computelayout->addWidget(btn[16], 5, 1, 1, 1);
    computelayout->addWidget(btn[17], 5, 2, 1, 1);
    computelayout->addWidget(btn[18], 5, 3, 2, 1);
    computelayout->addWidget(btn[19], 5, 4, 2, 1);
    computelayout->addWidget(btn[20], 6, 0, 1, 2);
    computelayout->addWidget(btn[21], 6, 2, 1, 1);

###逻辑设计部分

首先先将每个按钮都绑定对应的 槽函数

    //from widget.cpp

    for(int i=0; i<22; i++){
        btn[i] = new QPushButton(that);
        btn[i]->setText(btnstr[i]);
        btn[i]->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        connect(btn[i],&QPushButton::clicked,that,[=](){         //这里
            that->input(btnstr[i], lineedit, label);
        });
    }

用户按下 = 按钮后,利用按钮的信号和槽调用 input() 函数


    //from widget.cpp

    void Widget::input(QString word, QLineEdit* lineedit, QLabel* label)
    {
        if(word == "="){
            if(linetxt == "")   label->setText("不能为空哦...");         // 首先判断表达式是否合法
            else    compute(lineedit, label);                           //合法,跳转到计算函数
        }
        else if (word == "More") {              //切换贷款计算界面
            this->hide();
            emit calchangewindow();
        }
        else if (word == "CE") {                //清空
            linetxt = "";
            labeltxt = "";
            label->setText("");
            lineedit->setText(linetxt);
        }
        else if (word == "Del") {               //后退
            QString tmp = "";
            for (int i=0; i < linetxt.length()-1; i++)
                tmp += linetxt[i];
            linetxt = tmp;
            lineedit->setText(linetxt);
        }
        else {
            linetxt+=word;                         //输入为字符
            lineedit->setText(linetxt);
        }
    }

计算时我们需要先将 中缀表达式 转化为 后缀表达式

中缀表达式就是我们日常生活中正常使用的那种形如:a+b*c

后缀表达式就是形如abc*+,操作符在数字后面;

为什么有后缀表达式呢?

因为中缀表达式便于人们的理解与计算

但是后缀表达式更方便计算机的运算(如二叉树、堆栈的方法计算)

因此在读取一个中缀表达式后,我们得办法将他转化为后缀表达式。

那么怎么转化为后缀表达式呢?

我们可以用这种方法将中缀表达式转化为后缀表达式

以下是节选自项目 backans.cpp 的实现将中缀表达式转化后缀表达式的函数


    //from backans.cpp

    string getback(string str)//获取后缀表达式的函数
    {
        char* middle = new char[100];
        char* tmp = middle;
        char* isFirst = tmp;
        for (int i=0; i<str.length(); i++) {
            *tmp = str[i];                                    //将 middle 所指向的字符串内容赋值为传入的 str ,同时保持 middle 指向首地址不变
            tmp++;
        }
        char* back = new char[100];             //同上
        char* backend = back;
        stack<char> s;
        s.push('#');
        while (*middle)
        {
            if( ((middle == isFirst)&& *middle == '-' && Number(*(middle+1))) || ( *(middle-1) == '(' && *middle == '-' && Number(*(middle+1))) || Number(*middle))
            {
                *back = *middle;                                       //判断是否为负数
                back++, middle++;
            }
            else
            {
                if (Number(*(back - 1)))    *back++ = ' ';     //如果前一位是数字的话添加空格 用以区分

                if (*middle == ')')//如果右括号的话,输出所有操作符直到遇到左括号,并抛弃相对应的一堆括号
                {
                    while (s.top() != '(' && s.top() != '#')
                    {
                        *back = s.top();
                        s.pop();
                        back++;
                            *back++ = ' ';
                    }
                    middle++;
                    s.pop();//抛弃左括号
                }
                else if (*middle == '(')//遇到左括号,则进入栈
                {
                    s.push(*middle); middle++;
                }
                else if (priority(*middle) > priority(s.top()))//如果栈内的操作符优先级高于栈外的优先级,则入栈
                {
                    s.push(*middle); middle++;
                }
                else if (priority(*middle) <= priority(s.top()))
                                                        //如果栈内的操作符优先级低于或等于栈外的优先级,输出栈内的符号,并入栈栈外的符号
                {
                    while (priority(*middle) <= priority(s.top()) && s.top() != '#') {
                        *back = s.top();
                        back++;                                                                 //直到栈内的操作符为空 或者 低于栈外的优先级
                        s.pop();
                            *back++ = ' ';
                    }
                    s.push(*middle);
                    middle++;
                }
            }
        }
        while (isOpe(s.top()))//中缀表达式遍历完成,但是=栈中还有符号存在,一一出栈输出
        {
            if (Number(*(back - 1)))    *back++ = ' ';
            *back = s.top();
            qDebug("%c",*back);
            s.pop();
            if(s.top() != '#'){
                back++;
                *back++ = ' ';
            }
        }
        string tmpresult = "";                      //后面这些由于某些蜜汁bug而做出的一些处理。。。请无视充满了妥协
        string result = "";
        int address = 0;
        for (;backend<=back;backend++)
            tmpresult += *backend;
        while(Number(tmpresult[address]) || isOpe(tmpresult[address]) || tmpresult[address] == ' ')
            result += tmpresult[address++];

        return result;
    }

转化为后缀表达式后怎么计算结果呢?

我们可以用这种方法将后缀表达式求值

然后将结果打印至 lineEdit 即完成计算啦!

以下是节选自项目 backans.cpp 的实现计算后缀表达式的函数


    //from backans.cpp

    long double backans::result(string str)
    {
        string back = getback(str);
        stack<long double> s;
        for (int i=0; i<back.length(); ) {
            if(!isOpe(back[i]) || (back[i] == '-' && Number(back[i+1]) )){                      //将数字依次入栈
                s.push(turnnum(back, i));
                while (back[i] != ' ')
                    i++;
                i++;
            }
            else {
                long double a = s.top();
                s.pop();
                long double b = s.top();
                s.pop();
                s.push(Cauculate(back[i], b, a));//遇到符号时,取栈顶的第二个数和第一个数求解,并入栈
                i+=2;
            }
        }
        while (s.size() >= 2)//最终栈内存在的数大于2时,继续计算,直到只剩下一个数
        {
            long double a = s.top();
            s.pop();
            long double b = s.top();
            s.pop();
            s.push(Cauculate(back[back.length()-1], b, a));
        }
        //返回这个数字,既是最终结果
        return s.top();
    }

以上就是全部内容啦,希望能帮到您嘿嘿🤭

项目压缩包下载地址:https://files-cdn.cnblogs.com/files/Trump-He/Calculator.zip

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Qt简易计算器是一个基于Qt框架开发的简单计算器应用程序。它可以进行基本的数学运算,如加法、减法、乘法和除法。以下是一个示例代码: ```cpp #include <QApplication> #include <QGridLayout> #include <QPushButton> #include <QLineEdit> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建主窗口 QWidget window; window.setWindowTitle("Qt简易计算器"); // 创建显示结果的文本框 QLineEdit *resultLineEdit = new QLineEdit(&window); resultLineEdit->setReadOnly(true); // 创建数字按钮 QPushButton *buttons[10]; for (int i = 0; i < 10; ++i) { buttons[i] = new QPushButton(QString::number(i), &window); } // 创建运算符按钮 QPushButton *addButton = new QPushButton("+", &window); QPushButton *subtractButton = new QPushButton("-", &window); QPushButton *multiplyButton = new QPushButton("*", &window); QPushButton *divideButton = new QPushButton("/", &window); QPushButton *equalButton = new QPushButton("=", &window); // 创建布局管理器 QGridLayout *layout = new QGridLayout(&window); // 设置按钮位置 layout->addWidget(resultLineEdit, 0, 0, 1, 4); layout->addWidget(buttons, 1, 0); layout->addWidget(buttons, 1, 1); layout->addWidget(buttons, 1, 2); layout->addWidget(addButton, 1, 3); layout->addWidget(buttons, 2, 0); layout->addWidget(buttons, 2, 1); layout->addWidget(buttons, 2, 2); layout->addWidget(subtractButton, 2, 3); layout->addWidget(buttons, 3, 0); layout->addWidget(buttons, 3, 1); layout->addWidget(buttons, 3, 2 layout->addWidget(multiplyButton, 3, 3); layout->addWidget(buttons, 4, 0); layout->addWidget(equalButton, 4, 1); layout->addWidget(divideButton, 4, 2); // 连接按钮的点击事件到槽函数 QObject::connect(addButton, &QPushButton::clicked, [&]() { resultLineEdit->setText(QString::number(resultLineEdit->text().toInt() + resultLineEdit->text().toInt())); }); QObject::connect(subtractButton, &QPushButton::clicked, [&]() { resultLineEdit->setText(QString::number(resultLineEdit->text().toInt() - resultLineEdit->text().toInt())); }); QObject::connect(multiplyButton, &QPushButton::clicked, [&]() { resultLineEdit->setText(QString::number(resultLineEdit->text().toInt() * resultLineEdit->text().toInt())); }); QObject::connect(divideButton, &QPushButton::clicked, [&]() { resultLineEdit->setText(QString::number(resultLineEdit->text().toInt() / resultLineEdit->text().toInt())); }); QObject::connect(equalButton, &QPushButton::clicked, [&]() { // 执行等号操作,计算结果 // 这里可以根据需要自行实现 // 示例:将结果显示在文本框中 resultLineEdit->setText("计算结果"); }); // 显示主窗口 window.setLayout(layout); window.show(); return app.exec(); } ``` 这段代码创建了一个简单的计算器界面,包含数字按钮、运算符按钮和一个显示结果的文本框。通过连接按钮的点击事件到相应的槽函数,可以实现基本的计算功能。你可以根据需要自行完善等号按钮的点击事件,实现具体的计算逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值