学Q5不久,小试牛刀Qt5 编写的简单计算器

下面是源码

//calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H

#include<QTextEdit>
#include<QPushButton>
#include<QAction>
//#include<QtWidgets>
#include<QVector>
/*
先将表达式的单个字符依次存储到容器内,当出现“=”时,再将其
取出送入到相应的操作数容器和操作符容器为尽可能的接受用户不
规范的输入,设置了很多标志开关,有些乱还有bug未能解决.
*/
class Calculator : public QWidget
{
   Q_OBJECT

public:
   Calculator(QWidget *parent = 0);
   ~Calculator();
private:
   QTextEdit*  screenTextEdit;//表达式显示屏
   QPushButton*    button1;
   QPushButton*    button2;
   QPushButton*    button3;
   QPushButton*    button4;
   QPushButton*    button5;
   QPushButton*    button6;
   QPushButton*    button7;
   QPushButton*    button8;
   QPushButton*    button9;
   QPushButton*    button0;
   QPushButton*    buttonx;// sign '*'
   QPushButton*    buttondivide;// sign '/'
   QPushButton*    buttonadd;// sign '+
   QPushButton*    buttonsub;// sign '-'
   QPushButton*    buttondot;// sign '.'
   QPushButton*    buttonequal;// sign '='
   QPushButton*    buttonclear;//清屏
   QPushButton*    buttonback;// backspace
   QPushButton*    buttonLArc;// sign '('
   QPushButton*    buttonRArc;// sign ')'
   bool isEnter;//作为是否换行的依据,注意是光标先换行
   double sum ;//临时存放操作数
   int i;//转化成小数的除数
   int j;//压入操作数栈的开关
   double result;//计算所得结果
   bool isPoint;//是否出现小数点
   bool isLArc;//标记是否出现(以便判断区分出类似'(-2'形式
   char sign;//用来存放符号
   bool isTwoOptrsFlag;//++, -+ ...
   bool isEqualClicked;//作为是否回退容器内的字符的开关
   int f1[7];//栈内符号优先级
   int f2[7];//栈外符号优先级
   //建立操作数和操作符的栈
   QVector<double>vectorOpnd;
   QVector<char>vectorOptr;
   QVector<char>vectorExp;

   bool isTwoOptr(QPushButton *button);//++, -+ ...
   void initConnect();
   void initVector();
   double operate(double a, char theat, double b);//进行两个操作数的运算,返回结果
   char precedeSign(char optr1, char optr2);//比较栈内和栈外符号的优先级
   int char2num(char optr);//获取符号在优先级数组中的序号
   void initData();//初始化各个标志变量
   char button2char(QPushButton *button);//按钮转化为相应符号
   void getDigital(char digital);//进行数字的进栈操作
   void getSign(char ch);//获取符号
   bool pickSign(char ch);//分拣符号,以便进行相应的操作
   bool pushVector(char optr);//进行符号的进栈操作
   void getResult();//
private slots:
   void getButton();//获取按下的按钮
   void clearScreen();//清屏
   void myBackSpace();//执行backspace

};

#endif // CALCULATOR_H


//calculator.cpp

#include "calculator.h"
#include<QGridLayout>
//#include<QDebug>

Calculator::Calculator(QWidget *parent)
   : QWidget(parent)
 {
   initData();
   setWindowTitle("计算器");
   setWindowIcon(QIcon(":/calculator.png"));
   screenTextEdit = new QTextEdit;
   screenTextEdit->setFont(QFont("Courier 10 Pitch", 18, QFont::Bold));
   screenTextEdit->setReadOnly(true);
//   screenTextEdit->setEnabled(false);
   button1 = new QPushButton("1");
   button2 = new QPushButton("2");
   button3 = new QPushButton("3");
   button4 = new QPushButton("4");
   button5 = new QPushButton("5");
   button6 = new QPushButton("6");
   button7 = new QPushButton("7");
   button8 = new QPushButton("8");
   button9 = new QPushButton("9");
   button0 = new QPushButton("0");
   buttonx = new QPushButton("×");
   buttonadd = new QPushButton("+");//
   buttonsub = new QPushButton("-");
   buttonback = new QPushButton("back");
   buttondivide = new QPushButton("/");
   buttondot = new QPushButton(".");
   buttonLArc = new QPushButton("(");
   buttonRArc = new QPushButton(")");
   buttonequal = new QPushButton("=");
   buttonclear = new QPushButton("clear");

   initConnect();

   QGridLayout *gridLayout = new QGridLayout;
   gridLayout->addWidget(screenTextEdit, 0, 0, 2, 5);
   gridLayout->addWidget(button1, 2, 0, 1, 1);
   gridLayout->addWidget(button2, 2, 1, 1 ,1);
   gridLayout->addWidget(button3, 2, 2, 1, 1);
   gridLayout->addWidget(buttonadd, 2, 3, 1, 1);
   gridLayout->addWidget(buttonsub, 2, 4, 1, 1);
   gridLayout->addWidget(button4, 3, 0, 1, 1);
   gridLayout->addWidget(button5, 3, 1, 1, 1);
   gridLayout->addWidget(button6, 3, 2, 1, 1);
   gridLayout->addWidget(buttonx, 3, 3, 1, 1);
   gridLayout->addWidget(buttondivide, 3, 4, 1, 1);
   gridLayout->addWidget(button7, 4, 0, 1, 1);
   gridLayout->addWidget(button8, 4, 1, 1, 1);
   gridLayout->addWidget(button9, 4, 2, 1, 1);
   gridLayout->addWidget(buttonLArc, 4, 3, 1, 1);
   gridLayout->addWidget(buttonRArc, 4, 4, 1, 1);
   gridLayout->addWidget(button0, 5, 0, 1, 1);
   gridLayout->addWidget(buttondot, 5, 1, 1, 1);
   gridLayout->addWidget(buttonback, 5, 2, 1, 1);
   gridLayout->addWidget(buttonclear, 5, 3, 1, 1);
   gridLayout->addWidget(buttonequal, 5, 4, 1, 1);

   setLayout(gridLayout);
   initVector();
}
void Calculator::initConnect()
{
   connect(button0, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button1, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button2, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button3, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button4, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button5, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button6, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button7, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button8, &QPushButton::clicked, this, &Calculator::getButton);
   connect(button9, &QPushButton::clicked, this, &Calculator::getButton);
   connect(buttonx, &QPushButton::clicked, this, &Calculator::getButton);
   connect(buttonadd, &QPushButton::clicked, this, &Calculator::getButton);
   connect(buttondivide, &QPushButton::clicked, this, &Calculator::getButton);
   connect(buttondot, &QPushButton::clicked, this, &Calculator::getButton);
   connect(buttonsub, &QPushButton::clicked, this, &Calculator::getButton);
   connect(buttonRArc, &QPushButton::clicked, this, &Calculator::getButton);
   connect(buttonLArc, &QPushButton::clicked, this, &Calculator::getButton);

   connect(buttonback, &QPushButton::clicked, this, &Calculator::myBackSpace);
   connect(buttonclear, &QPushButton::clicked, this, &Calculator::clearScreen);
   connect(buttonequal, &QPushButton::clicked, this, &Calculator::getButton);
}

bool Calculator::isTwoOptr(QPushButton *button)
{
   if(button == buttonadd || button ==buttonsub
           || button == buttonx || button == buttondivide)
       return true;
   else
       return false;
}
void Calculator::myBackSpace()
{
   QTextCursor cursor = screenTextEdit->textCursor();
   cursor.deletePreviousChar();
   if(!isEqualClicked)
       vectorExp.pop_back();

}

void Calculator::getButton()
{
   QPushButton* button = qobject_cast<QPushButton*>(sender());
   if(isTwoOptrsFlag && isTwoOptr(button))
   {

   }
   else{

       vectorExp.append(button2char(button));
       isEqualClicked = false;
       isTwoOptrsFlag = false;
       if(!isEnter)
           screenTextEdit->append("");
       screenTextEdit->insertPlainText(button->text());
       isEnter = true;
       if(button == buttonadd || button == buttonsub
           || button == buttonx || button == buttondivide)
       isTwoOptrsFlag = true;
   }

   if(button == buttonequal)
   {
       isEqualClicked = true;
       getResult();
   }
}

void Calculator::getResult()
{
   while(!vectorExp.isEmpty())
   {
       char ch = vectorExp.first();
       vectorExp.removeFirst();
       getDigital(ch);
       getSign(ch);
   }
}
void Calculator::getDigital(char digital)
{
   if(digital == '0' || digital == '1' || digital == '2'
           || digital == '3' || digital == '4' || digital == '5'
           || digital == '6' || digital == '7' || digital == '8'
           || digital == '9' )
   {
       if(isPoint)
           i *= 10;//i初值是1
       j = 0;//j标记是否连续字符输入
       sum = sum * 10 + (digital - '0');
       isLArc = false;

   }
   else if(digital == '.')
   {
       isPoint = true;
       isLArc = false;
   }
}

void Calculator::getSign(char ch)
{
   if(isLArc && ch != '(' && ch != ')')
   {
       sign = ch;
   }
   else if(ch == '+' || ch == '-'
           || ch == '*' || ch == '/'
           || ch == '=' ||  ch == '('
           || ch == ')')
   {
       if(ch == '(')
           isLArc = true;
       else
           isLArc = false;

       j++;
       if(j <=1)
       {
           if(sign == '-')
               sum = sum * (-1);
           sign = ' ';
           vectorOpnd.append(sum / i);
           isLArc = false;
           i = 1;
           sum = 0;
           isPoint = false;
       }
       pickSign(ch);

    }
}


bool Calculator::pickSign(char ch)
{
   char theta;
   double a, b;
   if(ch == '=')
   {
       while(vectorOptr.last() != '#')
       {
           do{
               theta = vectorOptr.last();
               vectorOptr.pop_back();
           }while(theta == '(' || theta == ')');

           if(theta != '#')//void 8(,9),8()
           {
               b = vectorOpnd.last();vectorOpnd.pop_back();
               a = vectorOpnd.last();vectorOpnd.pop_back();
               vectorOpnd.append(operate(a, theta, b));
           }
           else if(theta == '#')
                   vectorOptr.append('#');
       }
       result = vectorOpnd.last();
       screenTextEdit->insertPlainText(QString("%1").arg(result));
       vectorOpnd.clear();
       vectorOptr.clear();
       initVector();
       isEnter = false;
       return true;
   }
   pushVector(ch);
   return true;
}

bool Calculator::pushVector(char optr)
{
   char theta;
   double a, b;
   if(optr == ')')
   {
       do{
           theta = vectorOptr.last();
           vectorOptr.pop_back();
       }while(theta == '(' || theta == ')');
       if(theta != '#')// void 8(,9),8()
       {
           b = vectorOpnd.last();vectorOpnd.pop_back();
           a = vectorOpnd.last();vectorOpnd.pop_back();
           vectorOpnd.append(operate(a, theta, b));
       }
       else
       {
           vectorOptr.append('#');
       }
       return true;
   }

   switch(precedeSign(vectorOptr.last(),optr))
   {
   case '<':
       vectorOptr.append(optr);
       break;
   case '=':
       vectorOptr.pop_back();
       break;
   case '>':
       theta = vectorOptr.last();
       vectorOptr.pop_back();
       b = vectorOpnd.last();
       vectorOpnd.pop_back();
       a = vectorOpnd.last();
       vectorOpnd.pop_back();
       vectorOpnd.append(operate(a, theta, b));
       vectorOptr.append(optr);
       break;
   }
   return true;
}
void Calculator::clearScreen()
{
   screenTextEdit->clear();
   result = 0;
   isEnter = true;
}

double Calculator::operate(double a, char theta, double b)
{
   double sum1;
   switch (theta) {
   case '+':
       sum1 = a + b;    break;
   case '-':
       sum1 = a - b;    break;
   case '*':
       sum1 = a * b;    break;
   case '/':
       sum1 = a / b;    break;
   }
   return sum1;
}

char Calculator::button2char(QPushButton *button)
{
   char optr;
   if(button == buttonadd)
       optr = '+';
   else if(button == buttonsub)
       optr = '-';
   else if(button == buttonx)
       optr = '*';
   else if(button == buttondivide)
       optr = '/';
   else if(button == buttonLArc)
       optr = '(';
   else if(button == buttonRArc)
       optr = ')';
   else if(button == buttonequal)
       optr = '=';
   else if(button == button0)
       optr = '0';
   else if(button == button1)
       optr = '1';
   else if(button == button2)
       optr = '2';
   else if(button == button3)
       optr = '3';
   else if(button == button4)
       optr = '4';
   else if(button == button5)
       optr = '5';
   else if(button == button6)
       optr = '6';
   else if(button == button7)
       optr = '7';
   else if(button == button8)
       optr = '8';
   else if(button == button9)
       optr = '9';
   else if(button == buttondot)
       optr = '.';
   return optr;
}
char Calculator::precedeSign(char optr1, char optr2)
{
   char compare;
    int i1 = char2num(optr1);
   int i2 = char2num(optr2);

   if(f1[i1] > f2[i2])
       compare =  '>';
   else if(f1[i1] < f2[i2])
           compare =  '<';
   else
       compare  = '=';
   return compare;

}
int Calculator::char2num(char optr)
{
   int ii;
   switch(optr)
   {
   case '+':
       ii = 0;   break;
   case '-':
       ii = 1;   break;
   case '*':
       ii = 2;   break;
   case '/':
       ii = 3;   break;
   case '(':
       ii =  4;   break;
   case ')':
       ii =  5;   break;
   default:
       ii = 6;
   }
   return ii;
}
void Calculator::initData()
{
   i = 1;
   j = 0;
   sum = 0;
   f1[0] = f1[1] =3;    f1[2] = f1[3] = 5;  f1[4] = 1;
   f1[5] = 6;  f1[6] = 0;
   f2[0] = f2[1] = 2;  f2[2] = f2[3]  = 4; f2[4] = 6;
   f2[5] = 1;  f2[6] = 0;
   isPoint = false;
   isLArc = false;
   sign = ' ';
   isTwoOptrsFlag = false;
   isEqualClicked = false;
   isEnter = true;
}

void Calculator::initVector()
{
   vectorOptr.append('#');
   vectorOpnd.append(0);
   vectorOpnd.append(0);
   vectorOpnd.append(0);
}

Calculator::~Calculator()
{

}

//main.cpp

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

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   Calculator cal;
   cal.show();

   return a.exec();
}