原创,转载请注明出处。
这里用Qt5实现了科学计算器的功能,添加了历史记录,以及标准计算器和科学计算器的转换,界面设置如下图:
在创建时使用基类使用QMainWindow,并创建界面文件。
将每个按键的名字改成我们可以识别的符号,例如数字键1改成digtalBtn1,如下图:
在mainwindow.h 的代码如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void myslot();
private slots:
void on_clearBtn_clicked();
void on_clearAllBtn_clicked();
void on_equalBtn_clicked();
void on_signBtn_clicked();
void on_pointBtn_clicked();
void digitClicked();
void operatorClicked();
void on_action_triggered();
void on_action_2_triggered();
void on_action_3_triggered();
void on_action_4_triggered();
void specialOperatorClicked();
void on_action_5_triggered();
private:
Ui::MainWindow *ui;
void abortOperation();
void connectSlots();//连接信号和槽
bool waitForOperand;//标记是否等待一个操作数
void setShortcutKeys();
QString inToPost(QString infix) throw(const char*);//转换为后缀表达式
double compute(QString s) throw(const char*);//计算后缀表达式的结果
QString error;
QString log;
};
#endif // MAINWINDOW_H
在main.cpp文件中保持创建初始状态不变。
在mainwindow.cpp的代码如下所示:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include
#include
#include
#include
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->lineEdit->setText("0");
waitForOperand=true;
connectSlots();
setShortcutKeys();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::abortOperation()
{
ui->lineEdit->setText("0");
waitForOperand=true;
QMessageBox::warning(this,"运算错误","错误!");
}
void MainWindow::connectSlots()
{
QPushButton *digitaBtns[10]={
ui->digtalBtn0,ui->digtalBtn1,ui->digtalBtn2,ui->digtalBtn3,ui->digtalBtn4,ui->digtalBtn5,ui->digtalBtn6,ui->digtalBtn7,ui->digtalBtn8,ui->digtalBtn9
};
for(auto btn:digitaBtns)
connect(btn,&QPushButton::clicked,this,&MainWindow::digitClicked);
QPushButton *operatorBtns[8]={
ui->addBtn,ui->subtractionBtn,ui->mulBtn,ui->divBtn,ui->leftBracketBtn,ui->rightBracketBtn,ui->powBtn,ui->percrntBtn
};
for(auto btn:operatorBtns)
connect(btn,&QPushButton::clicked,this,&MainWindow::operatorClicked);
QPushButton *specialOperatorBtns[5]={
ui->sinBtn,ui->cosBtn,ui->tanBtn,ui->lnBtn,ui->lgBtn
};
for(auto btn:specialOperatorBtns)
connect(btn,&QPushButton::clicked,this,&MainWindow::specialOperatorClicked);
}
void MainWindow::setShortcutKeys()
{
Qt::Key key[27]={Qt::Key_0,Qt::Key_1,Qt::Key_2,Qt::Key_3,Qt::Key_4,Qt::Key_5,Qt::Key_6,Qt::Key_7,Qt::Key_8,Qt::Key_9,Qt::Key_Plus,Qt::Key_Minus,Qt::Key_Asterisk,Qt::Key_Slash,
Qt::Key_Enter,Qt::Key_Period,Qt::Key_Backspace,Qt::Key_M,Qt::Key_ParenLeft,Qt::Key_ParenRight,Qt::Key_AsciiCircum,
Qt::Key_Percent,Qt::Key_S,Qt::Key_C,Qt::Key_T,Qt::Key_N,Qt::Key_G};
QPushButton *btn[27]={
ui->digtalBtn0,ui->digtalBtn1,ui->digtalBtn2,ui->digtalBtn3,ui->digtalBtn4,ui->digtalBtn5,ui->digtalBtn6,ui->digtalBtn7,ui->digtalBtn8,ui->digtalBtn9,
ui->addBtn,ui->subtractionBtn,ui->mulBtn,ui->divBtn,ui->equalBtn,ui->pointBtn,ui->clearAllBtn,ui->signBtn,ui->leftBracketBtn,ui->rightBracketBtn,ui->powBtn,
ui->percrntBtn,ui->sinBtn,ui->cosBtn,ui->tanBtn,ui->lnBtn,ui->lgBtn
};
for(int i=0;i<27;i++)
btn[i]->setShortcut(QKeySequence(key[i]));
ui->clearAllBtn->setShortcut(QKeySequence("Ctrl+Backspace"));
}
void MainWindow::digitClicked()
{
QPushButton *digitBtn=static_cast<QPushButton*>(sender());
QString value=digitBtn->text();
if(ui->lineEdit->text()=="0"&&value=="0")
return;
if(waitForOperand)
{
ui->lineEdit->setText(value);
waitForOperand=false;
}
else
{
ui->lineEdit->setText(ui->lineEdit->text()+value);
}
}
void MainWindow::operatorClicked()
{
QPushButton *clickedBtn=qobject_cast<QPushButton*>(sender());
QString clickedOperator=clickedBtn->text();
if(waitForOperand==true&&clickedOperator=='(')//首符号为‘(’的到时候
{
ui->lineEdit->setText(clickedOperator);
waitForOperand=false;
}
else if(waitForOperand==false)
ui->lineEdit->setText(ui->lineEdit->text()+clickedOperator);
//以上更具有鲁棒性
// if(waitForOperand==false&&ui->lineEdit->text().data()[ui->lineEdit->text().size()-1].isDigit()==true)//在 waitforoperand允许的情况下,并且字符串最后一个字符为数字的情况下
// ui->lineEdit->setText(ui->lineEdit->text()+clickedOperator);
// else if(waitForOperand==false&&clickedOperator=='(')
// ui->lineEdit->setText(ui->lineEdit->text()+clickedOperator);
// else if(waitForOperand==false&&ui->lineEdit->text().data()[ui->lineEdit->text().size()-1]=='%')
// ui->lineEdit->setText(ui->lineEdit->text()+clickedOperator);
// else if(waitForOperand==true&&clickedOperator=='(')//首符号为‘(’的到时候
// {
// ui->lineEdit->setText(clickedOperator);
// waitForOperand=false;
// }
}
void MainWindow::specialOperatorClicked()
{
QPushButton *specialOperatorBtn=static_cast<QPushButton*>(sender());
QString value=specialOperatorBtn->text();
if(waitForOperand)
{
ui->lineEdit->setText(value);
waitForOperand=false;
}
else
{
ui->lineEdit->setText(ui->lineEdit->text()+value);
}
}
void MainWindow::on_equalBtn_clicked()
{
double result=0.0;
try
{
result=compute(inToPost(ui->lineEdit->text()));
// QMessageBox::warning(this,"提示",inToPost(ui->lineEdit->text()));//查看后缀表达式
}
catch(const char *er)
{
error=er;
abortOperation();
return;
}
ui->lineEdit->setText(ui->lineEdit->text()+'='+QString::number(result));
log=ui->lineEdit->text();
waitForOperand=true;
}
void MainWindow::on_clearBtn_clicked()
{
//将显示字符串退格
QString str=ui->lineEdit->text();
if(str!='0'&&waitForOperand==false)
{
ui->lineEdit->setText(str.left(str.count()-1));
waitForOperand=false;
}
else
{
ui->lineEdit->setText("0");
waitForOperand=true;
}
}
void MainWindow::on_clearAllBtn_clicked()
{
//将当前显示全部归零
ui->lineEdit->setText("0");
waitForOperand=true;
}
void MainWindow::on_signBtn_clicked()
{
QString text=ui->lineEdit->text();
QChar sign=text[text.size()-1];
if(sign=='-')
{
text.remove(text.size()-1,1);
}
else {
text.append('-');
}
ui->lineEdit->setText(text);
}
void MainWindow::on_pointBtn_clicked()
{
if(waitForOperand==false&&ui->lineEdit->text().data()[ui->lineEdit->text().size()-1].isDigit()==true)
ui->lineEdit->setText(ui->lineEdit->text()+".");
}
QString MainWindow::inToPost(QString infix) throw(const char*)//将中缀表达式转换为后缀表达式
{
std::stack<char> stack;
char current=0;
QString postfix;
std::map<char,int> priority;
priority['+']=0;
priority['-']=0;
priority['*']=1;
priority['/']=1;
priority['^']=2;
priority['s']=3;
priority['c']=3;
priority['t']=3;
priority['n']=3;
priority['g']=3;
for(int i=0;i<infix.length();i++)
{
current=infix[i].toLatin1();
if(isdigit(current))
{
postfix.push_back(current);
continue;
}
switch (current)
{
case '+':
case '-':
case '*':
case '/':
case '^':
if(infix[i-1]!=')')
{
if(infix[i-1].isDigit())
postfix.push_back('#');
else if(infix[i-1]=='%')
{}
// infix.begin();
else
throw "expression is illegality";
}
if(stack.empty()==false)
{
char tempTop=stack.top();
while(tempTop!='('&&priority[current]<=priority[tempTop])
{
stack.pop();
postfix.push_back(tempTop);
if(stack.empty())
break;
tempTop=stack.top();
}
}
stack.push(current);
break;
case's':
case'c':
case't':
if(i>0&&infix[i-1].isDigit())
throw"表达式非法";
if(!stack.empty())
{
char temTop=stack.top();
while(temTop!='('&&priority[current]<priority[temTop])
{
stack.pop();
postfix.push_back(temTop);
if(stack.empty())
break;
temTop=stack.top();
}
}
stack.push(current);
i=i+2;
break;
case'l':
if(i>0&&infix[i-1].isDigit())
throw"表达式非法";
if(!stack.empty())
{
char temTop=stack.top();
while(temTop!='('&&priority[infix[i+1].toLatin1()]<priority[temTop])
{
stack.pop();
postfix.push_back(temTop);
if(stack.empty())
break;
temTop=stack.top();
}
}
stack.push(infix[i+1].toLatin1());
i=i+1;
break;
case'.':
postfix.push_back(current);
break;
case'%':
postfix.push_back('#');
postfix.push_back(current);
break;
case'(':
stack.push(current);
break;
case')':
if(infix[i-1]!='%')
postfix.push_back('#');//右括号说明前方数字输入完成 标识一下
char temTop;
temTop=stack.top();
while (temTop!='(') {
stack.pop();
postfix.push_back(temTop);
temTop=stack.top();
}
stack.pop();
break;
default:
throw "expression has illegality charactor";
break;
}
}
if(infix[infix.size()-1]!=')')
{
if(infix[infix.size()-1].isDigit())
postfix.push_back('#');
else if(infix[infix.size()-1]=='%')
{}
else
throw "expression is illegality";
}
while(!stack.empty())
{
char tempOut=stack.top();
stack.pop();
postfix.push_back(tempOut);
}
return postfix;
}
double MainWindow::compute(QString s) throw(const char*)//计算后缀表达式
{
std::stack<double> stack;
QString str;
double curr;
double temNum1;
double temNum2;
for(auto i=s.begin();i!=s.end();i++)
{
if((*i).isDigit())
{
str.push_back(*i);
continue;
}
switch ((*(i)).toLatin1())
{
case '+':
temNum1=stack.top();
stack.pop();
temNum2=stack.top();
stack.pop();
stack.push(temNum2+temNum1);
break;
case '-':
temNum1=stack.top();
stack.pop();
temNum2=stack.top();
stack.pop();
stack.push(temNum2-temNum1);
break;
case '*':
temNum1=stack.top();
stack.pop();
temNum2=stack.top();
stack.pop();
stack.push(temNum2*temNum1);
break;
case '/':
temNum1=stack.top();
stack.pop();
temNum2=stack.top();
stack.pop();
stack.push(temNum2/temNum1);
break;
case '^':
temNum1=stack.top();
stack.pop();
temNum2=stack.top();
stack.pop();
stack.push(pow(temNum2,temNum1));
break;
case '.':
str.push_back(*i);
break;
case'#':
curr=str.toDouble();
str.clear();
stack.push(curr);
break;
case'%':
curr=stack.top();
stack.pop();
curr*=0.01;
stack.push(curr);
break;
case's':
temNum1=stack.top();
stack.pop();
stack.push(std::sin(temNum1/180.0*M_PI));
break;
case'c':
temNum1=stack.top();
stack.pop();
stack.push(std::cos(temNum1/180.0*M_PI));
break;
case't':
temNum1=stack.top();
stack.pop();
stack.push(std::tan(temNum1/180.0*M_PI));
break;
case'n':
temNum1=stack.top();
stack.pop();
stack.push(std::log10(temNum1));
break;
case'g':
temNum1=stack.top();
stack.pop();
stack.push(std::log(temNum1));
break;
default:
throw "illeaglity";
break;
}
}
curr=stack.top();
return curr;
}
void MainWindow::on_action_triggered()//实现粘贴功能
{
QClipboard *board= QApplication::clipboard();
QString text=board->text();
ui->lineEdit->setText(text);
}
void MainWindow::on_action_2_triggered()//显示历史记录
{
if(log.isEmpty()==true)
log="No History";
ui->lineEdit->setText(log);
waitForOperand=true;
}
void MainWindow::on_action_3_triggered()//清除历史记录
{
log.clear();
}
void MainWindow::on_action_4_triggered()
{
ui->percrntBtn->show();
ui->sinBtn->show();
ui->cosBtn->show();
ui->tanBtn->show();
ui->lnBtn->show();
ui->lgBtn->show();
}
void MainWindow::on_action_5_triggered()
{
ui->percrntBtn->hide();
ui->sinBtn->hide();
ui->cosBtn->hide();
ui->tanBtn->hide();
ui->lnBtn->hide();
ui->lgBtn->hide();
}
运行之后便得到了一个简单的科学计算器。
下节介绍一些关于此代码的关键的地方的理解。