Qt5 计算器的实现

零零散散学了段时间的Qt5,今天动手写了个计算器,太开心了。在这里,认真总结一下,其实在Qt里写带gui的程序,其实核心算法,直接把C/C++代码添加进去就可以了,所以还是要打牢C/C++的算法基础,真的是万变不离其宗啊。

工程文件下载链接在博客后面

首先看我的程序结构: 

我们都知道,计算器稍微麻烦点的就是中缀表达式转后缀表达式,以及后缀表达式的计算,我这里func.c就是这篇博客中缀表达式转后缀,后缀表达式计算里的代码,当然头文件不一样,大家可以比对一下

func.h

#ifndef FUNC_H
#define FUNC_H
#include<iostream>
#include<stack>
#include<ctype.h>
#include<vector>
using namespace std;
int instack(string c);
int outstack(string c);
vector<string> InfixToPostfix(string str);
bool operation(string tmp,stack<double> &stk);
double postfix2ans(vector<string> exp);
void test();
#endif // FUNC_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QGridLayout>
#include <QVBoxLayout>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
private:
    QPushButton *No_0Btn;
    QPushButton *No_1Btn;
    QPushButton *No_2Btn;
    QPushButton *No_3Btn;
    QPushButton *No_4Btn;
    QPushButton *No_5Btn;
    QPushButton *No_6Btn;
    QPushButton *No_7Btn;
    QPushButton *No_8Btn;
    QPushButton *No_9Btn;

    QPushButton *addBtn;
    QPushButton *minusBtn;
    QPushButton *multiplyBtn;
    QPushButton *divideBtn;

    QPushButton *pointBtn;
    QPushButton *equalBtn;

    QLineEdit *displayLineEdit;

    QVBoxLayout *mainLayout;
    QVBoxLayout *topLayout;
    QGridLayout *bottomLayout;

    int calculatorFlag;
    bool equalFlag;
private slots:
    void No_0BtnClicked();
    void No_1BtnClicked();
    void No_2BtnClicked();
    void No_3BtnClicked();
    void No_4BtnClicked();
    void No_5BtnClicked();
    void No_6BtnClicked();
    void No_7BtnClicked();
    void No_8BtnClicked();
    void No_9BtnClicked();

    void addBtnClicked();
    void minusBtnClicked();
    void multiplyBtnClicked();
    void divideBtnClicked();

    void pointBtnClicked();
    void equalBtnClicked();
};

#endif // WIDGET_H

 func.cpp,就是C++的程序

#include"func.h"
int instack(string c)//堆栈内部的运算符优先级
{
    int priority;
    if(c=="(")
        priority=0;
    if(c=="+"||c=="-")
        priority=1;
    if(c=="*"||c=="/")
        priority=2;
    if(c=="#")
        priority=0;
    return priority;
}
int outstack(string c)//堆栈外的运算符优先级
{
    int priority;
    if(c=="(")
        priority=3;
    if(c=="+"||c=="-")
        priority=1;
    if(c=="*"||c=="/")
        priority=2;
    return priority;
}
vector<string> InfixToPostfix(string str)
{
    vector<string> exp,res;
    string tstr="";
    for(int i=0;i<str.length();i++)
    {
        //cout<<i<<endl;
        if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'||str[i]=='('||str[i]==')')
        {
            if(tstr.length()!=0)
            {
                exp.push_back(tstr);
                tstr="";
            }
            tstr+=str[i];
            exp.push_back(tstr);
            tstr="";
        }
        else
        {
            tstr+=str[i];
        }
    }
    if(tstr.length()!=0)
        exp.push_back(tstr);
    exp.push_back("#");
    stack<string> stk;//存放 运算符和括号的栈
    stk.push("#");
    //string test="#";
    string st="";
    //cout<<exp.size()<<endl;
    //int i=0;
    for(int i=0;i<exp.size()-1;i++)//for(i=0,st=exp[i];exp[i]!="#";i++,st=exp[i])
    {
        st=exp[i];
        if(st==")")
        {
            while(stk.top()!="(")
            {
                res.push_back(stk.top());
                stk.pop();
            }
            stk.pop();
        }
        else if(st=="+"||st=="-"||st=="*"||st=="/"||st=="("||st=="#")
        {
            while(instack(stk.top())>=outstack(st))
            {
                res.push_back(stk.top());
                stk.pop();
            }
            stk.push(st);
        }
        else
        {
            res.push_back(st);
        }
    }
    while(!stk.empty())
    {
        if(stk.top()!="#")
        {
            res.push_back(stk.top());
        }
        stk.pop();
    }
    return res;
}

bool operation(string tmp,stack<double> &stk)
{
    double a=0,b=0;//操作数
    if(stk.size()<2)
    {
        cout<<"miss operator number"<<endl;
    }
    else
    {
        a=stk.top();
        stk.pop();
        b=stk.top();
        stk.pop();
        if(tmp=="+")
        {
            stk.push(b+a);
        }
        else if(tmp=="-")
        {
            stk.push(b-a);
        }
        else if(tmp=="*")
        {
            stk.push(b*a);
        }
        else if(tmp=="/")
        {
            if(a==0)
            {
                cout<<"denominator is 0!!!"<<endl;
                return false;
            }
            else
            {
                stk.push(b/a);
            }
        }
    }
    return true;
}

double postfix2ans(vector<string> exp)
{
    string tmp;//临时存放后缀表达式的每一项
    bool flag=true;
    stack<double> stk;
    for(int i=0;i<exp.size();i++)
    {
        tmp=exp[i];
        if(tmp=="+"||tmp=="-"||tmp=="*"||tmp=="/")
        {
            flag=operation(tmp,stk);
            if(!flag)
                return 0;
        }
        else
        {
            stk.push(atof(tmp.c_str()));//c_str是Borland封装的String类中的一个函数,它返回当前字符串的首字符地址。
        }
    }
    return stk.top();
}

widget.cpp

#include "widget.h"
#include"func.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    setWindowTitle(tr("简易计算器"));        //设置程序标题
    setMinimumSize(300,200);
    setMaximumSize(600,400);

    displayLineEdit = new QLineEdit();      //文本输入与显示

    No_0Btn = new QPushButton(tr("0"));     //0~9
    No_1Btn = new QPushButton(tr("1"));
    No_2Btn = new QPushButton(tr("2"));
    No_3Btn = new QPushButton(tr("3"));
    No_4Btn = new QPushButton(tr("4"));
    No_5Btn = new QPushButton(tr("5"));
    No_6Btn = new QPushButton(tr("6"));
    No_7Btn = new QPushButton(tr("7"));
    No_8Btn = new QPushButton(tr("8"));
    No_9Btn = new QPushButton(tr("9"));

    addBtn = new QPushButton(tr("+"));      //+-×÷.=
    minusBtn = new QPushButton(tr("-"));
    multiplyBtn = new QPushButton(tr("*"));
    divideBtn = new QPushButton(tr("/"));

    pointBtn = new QPushButton(tr("."));
    equalBtn = new QPushButton(tr("=/C"));

    mainLayout = new QVBoxLayout(this);     //创建主布局为垂直布局
    topLayout = new QVBoxLayout();          //为单行输入框创建垂直布局
    bottomLayout = new QGridLayout();       //为按键创建格子布局

    mainLayout->addLayout(topLayout);       //添加布局
    mainLayout->addLayout(bottomLayout);

    topLayout->addWidget(displayLineEdit);      //添加Widget

    bottomLayout->addWidget(No_7Btn,0,0);
    bottomLayout->addWidget(No_8Btn,0,1);
    bottomLayout->addWidget(No_9Btn,0,2);
    bottomLayout->addWidget(addBtn,0,3);

    bottomLayout->addWidget(No_4Btn,1,0);
    bottomLayout->addWidget(No_5Btn,1,1);
    bottomLayout->addWidget(No_6Btn,1,2);
    bottomLayout->addWidget(minusBtn,1,3);

    bottomLayout->addWidget(No_1Btn,2,0);
    bottomLayout->addWidget(No_2Btn,2,1);
    bottomLayout->addWidget(No_3Btn,2,2);
    bottomLayout->addWidget(multiplyBtn,2,3);

    bottomLayout->addWidget(No_0Btn,3,0);
    bottomLayout->addWidget(pointBtn,3,1);
    bottomLayout->addWidget(equalBtn,3,2);
    bottomLayout->addWidget(divideBtn,3,3);

    connect(No_0Btn,SIGNAL(clicked(bool)),this,SLOT(No_0BtnClicked()));     //按键连接
    connect(No_1Btn,SIGNAL(clicked(bool)),this,SLOT(No_1BtnClicked()));
    connect(No_2Btn,SIGNAL(clicked(bool)),this,SLOT(No_2BtnClicked()));
    connect(No_3Btn,SIGNAL(clicked(bool)),this,SLOT(No_3BtnClicked()));
    connect(No_4Btn,SIGNAL(clicked(bool)),this,SLOT(No_4BtnClicked()));
    connect(No_5Btn,SIGNAL(clicked(bool)),this,SLOT(No_5BtnClicked()));
    connect(No_6Btn,SIGNAL(clicked(bool)),this,SLOT(No_6BtnClicked()));
    connect(No_7Btn,SIGNAL(clicked(bool)),this,SLOT(No_7BtnClicked()));
    connect(No_8Btn,SIGNAL(clicked(bool)),this,SLOT(No_8BtnClicked()));
    connect(No_9Btn,SIGNAL(clicked(bool)),this,SLOT(No_9BtnClicked()));

    connect(addBtn,SIGNAL(clicked(bool)),this,SLOT(addBtnClicked()));
    connect(minusBtn,SIGNAL(clicked(bool)),this,SLOT(minusBtnClicked()));
    connect(multiplyBtn,SIGNAL(clicked(bool)),this,SLOT(multiplyBtnClicked()));
    connect(divideBtn,SIGNAL(clicked(bool)),this,SLOT(divideBtnClicked()));
    connect(pointBtn,SIGNAL(clicked(bool)),this,SLOT(pointBtnClicked()));
    connect(equalBtn,SIGNAL(clicked(bool)),this,SLOT(equalBtnClicked()));

    calculatorFlag = 0;     //计算标志位
    //pointFlag = equalFlag = false;      //等号标志位
    equalFlag=true;
}

Widget::~Widget()
{

}

void Widget::No_0BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("0"));
}

void Widget::No_1BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("1"));
}

void Widget::No_2BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("2"));
}

void Widget::No_3BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("3"));
}

void Widget::No_4BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("4"));
}

void Widget::No_5BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("5"));
}

void Widget::No_6BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("6"));
}

void Widget::No_7BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("7"));
}

void Widget::No_8BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("8"));
}

void Widget::No_9BtnClicked()
{
    if (equalFlag)
    {
        displayLineEdit->clear();
        displayLineEdit->setAlignment(Qt::AlignLeft);
        equalFlag = false;
    }
    displayLineEdit->setText(displayLineEdit->text()+=tr("9"));
}

void Widget::addBtnClicked()
{
    displayLineEdit->setText(displayLineEdit->text()+=tr("+"));
    calculatorFlag = 1;
}

void Widget::minusBtnClicked()
{
    displayLineEdit->setText(displayLineEdit->text()+=tr("-"));
    calculatorFlag = 2;
}

void Widget::multiplyBtnClicked()
{
    displayLineEdit->setText(displayLineEdit->text()+=tr("*"));
    calculatorFlag = 3;
}

void Widget::divideBtnClicked()
{
    displayLineEdit->setText(displayLineEdit->text()+=tr("/"));
    calculatorFlag = 4;
}

void Widget::pointBtnClicked()
{
        displayLineEdit->setText(displayLineEdit->text()+=tr("."));
}

void Widget::equalBtnClicked()
{
    if(equalFlag)
    {
        displayLineEdit->setText(displayLineEdit->text()="0");
    }
    else
    {
        displayLineEdit->setAlignment(Qt::AlignRight);
        displayLineEdit->setText(displayLineEdit->text()+="=");//displayLineEdit->text()+="=";
        QString res=displayLineEdit->text();
        string s = res.toStdString();
        double ans=postfix2ans(InfixToPostfix(s));
        displayLineEdit->setText(displayLineEdit->text()+=QString::number(ans));//displayLineEdit->text()+=QString::number(ans);
        displayLineEdit->setText(displayLineEdit->text()/*+="hello"*/);
    }
    equalFlag = true;
    calculatorFlag = 0;
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setWindowIcon(QIcon(":/image/newpic.png"));
    Widget w;
    w.show();

    return a.exec();
}

程序运行结果:

参考了这位朋友的代码,不过他的思路可能没理清,只能计算2个数的加减乘除,不能小数,也没有用到中缀表达式和后缀表达式,不过还是非常写写,我在ta的代码上前进了一大步。衷心地感谢。 

Calculator-master.zip

猜你喜欢

转载自blog.csdn.net/salmonwilliam/article/details/86578422