预习日志
1 设置窗口大小以及缓冲区大小
2 绘制整体界面
3 采用字符串保存数字字符
4 清空输入 输出区字符
5 其他功能 回退,清空,等于
代码实现
calculator.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QPushButton>
#include<QLineEdit>
#include<QHBoxLayout>
#include<QVBoxLayout>
#include<QGridLayout>
#include<QString>
#include<QStack>
#include<QTime>
#include<iterator>
class calculator : public QMainWindow
{
Q_OBJECT
public:
calculator(QWidget *parent = 0);
~calculator();
private:
QLineEdit *inputLine;
QLineEdit *historyList;
QString input="0";
bool flat=false;
QPushButton *zeroButton;
QPushButton *oneButton;
QPushButton *twoButton;
QPushButton *threeButton;
QPushButton *fourButton;
QPushButton *fiveButton;
QPushButton *sixButton;
QPushButton *sevenButton;
QPushButton *eightButton;
QPushButton *nineButton;
QPushButton *addButton;
QPushButton *subButton;
QPushButton *divButton;
QPushButton *mulButton;
QPushButton *equButton;
QPushButton *decButton;
QPushButton *botButton;
QPushButton *CEButton;
QPushButton *ACButton;
QPushButton *CButton;
QPushButton *lefButton;
QPushButton *rigButton;
private slots:
void buttonZeroClicked();
void buttonOneClicked();
void buttonTwoClicked();
void buttonThreeClicked();
void buttonFourClicked();
void buttonFiveClicked();
void buttonSixClicked();
void buttonSevenClicked();
void buttonEightClicked();
void buttonNineClicked();
void buttonAddClicked();
void buttonSubClicked();
void buttonMulClicked();
void buttonDivClicked();
void buttonDecClicked();
void buttonBotClicked();
void buttonEquClicked();
void buttonLefClicked();
void buttonRigClicked();
void buttonCEClicked();
void buttonCClicked();
void buttonACClicked();
};
#endif // MAINWINDOW_H
calculator.cpp文件
#include "calculator.h"
#include<iostream>
using namespace std;
#include<stack>
#include<vector>
#include<cstdlib>
#include<limits.h>
#pragma execution_character_set("utf-8")
bool isNum(char ch);
bool isOperate(char ch);
int level(char ch);
double scd(string s);
double getValue(vector<string> V);
vector<string> midToPost(string s);
calculator::calculator(QWidget *parent) : QMainWindow(parent)
{
QWidget *widget=new QWidget;
this->setCentralWidget(widget);
inputLine=new QLineEdit;
inputLine->setText(input);
historyList = new QLineEdit;
zeroButton=new QPushButton("0");
oneButton=new QPushButton("1");
twoButton=new QPushButton("2");
threeButton=new QPushButton("3");
fourButton=new QPushButton("4");
fiveButton=new QPushButton("5");
sixButton=new QPushButton("6");
sevenButton=new QPushButton("7");
eightButton=new QPushButton("8");
nineButton=new QPushButton("9");
decButton=new QPushButton(".");
addButton=new QPushButton("+");
subButton=new QPushButton("-");
mulButton=new QPushButton("*");
divButton=new QPushButton("/");
equButton=new QPushButton("=");
lefButton=new QPushButton("(");
rigButton=new QPushButton(")");
CEButton=new QPushButton("CE");
ACButton=new QPushButton("AC");
CButton=new QPushButton("C");
QGridLayout *H=new QGridLayout(this);
inputLine->setFixedHeight(50);
historyList->setFixedHeight(50);
H->addWidget(inputLine,0,0,1,5);
H->addWidget(historyList,5,0,1,4);
H->setRowStretch(0,100);
CButton->setFixedHeight(50);
H->addWidget(oneButton,1,0);
H->addWidget(twoButton,1,1);
H->addWidget(threeButton,1,2);
H->addWidget(CEButton,1,3);
H->addWidget(ACButton,1,4);
H->addWidget(fourButton,2,0);
H->addWidget(fiveButton,2,1);
H->addWidget(sixButton,2,2);
H->addWidget(addButton,2,3);
H->addWidget(subButton,2,4);
H->addWidget(sevenButton,3,0);
H->addWidget(eightButton,3,1);
H->addWidget(nineButton,3,2);
H->addWidget(mulButton,3,3);
H->addWidget(divButton,3,4);
H->addWidget(zeroButton,4,0);
H->addWidget(decButton,4,1);
H->addWidget(lefButton,4,2);
H->addWidget(rigButton,4,3);
H->addWidget(equButton,4,4);
H->addWidget(CButton,5,4);
widget->setLayout(H);
connect(zeroButton,SIGNAL(clicked()),this,SLOT(buttonZeroClicked()));
connect(oneButton,SIGNAL(clicked()),this,SLOT(buttonOneClicked()));
connect(twoButton,SIGNAL(clicked()),this,SLOT(buttonTwoClicked()));
connect(threeButton,SIGNAL(clicked()),this,SLOT(buttonThreeClicked()));
connect(fourButton,SIGNAL(clicked()),this,SLOT(buttonFourClicked()));
connect(fiveButton,SIGNAL(clicked()),this,SLOT(buttonFiveClicked()));
connect(sixButton,SIGNAL(clicked()),this,SLOT(buttonSixClicked()));
connect(sevenButton,SIGNAL(clicked()),this,SLOT(buttonSevenClicked()));
connect(eightButton,SIGNAL(clicked()),this,SLOT(buttonEightClicked()));
connect(nineButton,SIGNAL(clicked()),this,SLOT(buttonNineClicked()));
connect(addButton,SIGNAL(clicked()),this,SLOT(buttonAddClicked()));
connect(subButton,SIGNAL(clicked()),this,SLOT(buttonSubClicked()));
connect(mulButton,SIGNAL(clicked()),this,SLOT(buttonMulClicked()));
connect(divButton,SIGNAL(clicked()),this,SLOT(buttonDivClicked()));
connect(decButton,SIGNAL(clicked(bool)),this,SLOT(buttonDecClicked()));
connect(lefButton,SIGNAL(clicked(bool)),this,SLOT(buttonLefClicked()));
connect(rigButton,SIGNAL(clicked(bool)),this,SLOT(buttonRigClicked()));
connect(CEButton,SIGNAL(clicked()),this,SLOT(buttonCEClicked()));
connect(ACButton,SIGNAL(clicked()),this,SLOT(buttonACClicked()));
connect(CButton,SIGNAL(clicked()),this,SLOT(buttonCClicked()));
connect(equButton,SIGNAL(clicked()),this,SLOT(buttonEquClicked()));
}
void calculator::buttonZeroClicked()
{
if(input=="0")
input='0';
else input=input+'0';
inputLine->setText(input);
}
void calculator::buttonOneClicked()
{
if(input=="0")
input='1';
else input=input+'1';
inputLine->setText(input);
}
void calculator::buttonTwoClicked()
{
if(input=="0")
input='2';
else input=input+'2';
inputLine->setText(input);
}
void calculator::buttonThreeClicked()
{
if(input=="0")
input='3';
else input=input+'3';
inputLine->setText(input);
}
void calculator::buttonFourClicked()
{
if(input=="0")
input='4';
else input=input+'4';
inputLine->setText(input);
}
void calculator::buttonFiveClicked()
{
if(input=="0")
input='5';
else input=input+'5';
inputLine->setText(input);
}
void calculator::buttonSixClicked()
{
if(input=="0")
input='6';
else input=input+'6';
inputLine->setText(input);
}
void calculator::buttonSevenClicked()
{
if(input=="0")
input='7';
else input=input+'7';
inputLine->setText(input);
}
void calculator::buttonEightClicked()
{
if(input=="0")
input='8';
else input=input+'8';
inputLine->setText(input);
}
void calculator::buttonNineClicked()
{
if(input=="0")
input='9';
else input=input+'9';
inputLine->setText(input);
}
void calculator::buttonAddClicked()
{
if(input=="0")
input='+';
else input=input+'+';
inputLine->setText(input);
}
void calculator::buttonSubClicked()
{
if(input=="0")
input='-';
else input=input+'-';
inputLine->setText(input);
}
void calculator::buttonMulClicked()
{
if(input=="0")
input='*';
else input=input+'*';
inputLine->setText(input);
}
void calculator::buttonDivClicked()
{
if(input=="0")
input='/';
else input=input+'/';
inputLine->setText(input);
}
void calculator::buttonDecClicked()
{
if(input=="0")
input='.';
else input=input+'.';
inputLine->setText(input);
}
void calculator::buttonBotClicked()
{
if(input=="0")
input='-';
else
{
QString::iterator p=input.end();
p--;
if('-'==*p)
input=input.left(input.length()-1);
else input=input+'-';
}
inputLine->setText(input);
}
void calculator::buttonLefClicked()
{
if(input == "0")
{
input = "(";
}
else
{
char lastChar = input.back().toLatin1();
if(lastChar == '+' || lastChar == '-' || lastChar == '*' || lastChar == '/'||lastChar=='('||lastChar==')')
{
input = input + "(";
}
else
{
input = input + "=syntax error";
inputLine->setText(input);
return;
}
}
inputLine->setText(input);
}
void calculator::buttonRigClicked()
{
if(input == "0")
{
input = ")";
}
else
{
char lastChar = input.back().toLatin1();
if(isNum(lastChar)||lastChar=='('||lastChar==')')
{
input = input + ")";
}
else
{
input = input + "=syntax error";
inputLine->setText(input);
return;
}
}
inputLine->setText(input);
}
void calculator::buttonCEClicked()
{
input = input.left(input.length()-1);
inputLine->setText(input);
}
void calculator::buttonACClicked()
{
input = "0";
inputLine->setText(input);
}
void calculator::buttonCClicked()
{
historyList->clear();
}
void calculator::buttonEquClicked()
{
string inputTemp = input.toStdString();
vector<string> expression = midToPost(inputTemp);
double value = getValue(expression);
if(value != INT_MAX)
{
input = input + "=" + QString::number(value);
inputLine->setText(input);
QString history = historyList->text();
if(history.isEmpty())
{
historyList->setText(input);
}
else
{
historyList->setText(history + "\n" + input);
}
}
else { input = input + "=syntax error"; inputLine->setText(input);
}
}
bool isNum(char ch)
{
if(ch >= '0' && ch <= '9') return true;
else return false;
}
bool isOperate(char ch)
{
if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')')
return true;
else return false;
}
int level(char ch)
{
switch(ch)
{
case '(' :
return 5;
case '*' :
return 4;
case '/' :
return 4;
case '+' :
return 3;
case '-' :
return 3;
case ')':
return 2;
}
}
double scd(string s)
{
if(s.length() == 0) return INT_MAX;
bool flag = false;
for(int i = 0; i < s.length(); i++)
{
if(i == 0 && s[i] == '-') continue;
else if(s[i] == '.' && !flag)
{
if(i > 0 && isNum(s[i-1]))
{
flag = true;
continue;
}
else return INT_MAX;
}
else if(isNum(s[i])) continue;
else return INT_MAX;
}
double result = atof(s.c_str());
return result;
}
vector<string> midToPost(string s)
{
stack<char> S;
vector<string> V;
int i = 0;
while(i < s.length())
{
if(isNum(s[i]))
{
string str = "";
while(isNum(s[i]) || s[i] == '.')
{
str += s[i];
i++;
}
V.push_back(str);
}
else if(isOperate(s[i]))
{
if(s[i] == '-' && (i == 0 || !isNum(s[i-1])))
{
string str = "-"; i++;
while(isNum(s[i]) || s[i] == '.')
{
str += s[i]; i++;
}
V.push_back(str);
}
else
{
if(S.empty())
{
S.push(s[i]); i++;
}
else
{
int initial = level(s[i]);
if(initial == 2)
{
while(level(S.top()) != 5 && !s.empty())
{
string str = "";
str += S.top();
V.push_back(str);
S.pop();
}
if(S.top() == '(') S.pop();
i++;
}
else
{
while(!S.empty() && initial <= level(S.top()) && level(S.top()) != 5)
{
string str = "";
str += S.top();
V.push_back(str);
S.pop();
}
S.push(s[i]); i++;
}
}
}
}
else
{
cout << "表达式出错" << endl;
V.clear();
return V;
}
}
while(!S.empty())
{
string str = ""; str += S.top();
S.pop();
V.push_back(str);
}
//for(int i = 0; i < V.size(); i++) cout << V[i] << "[]";
return V;
}
double getValue(vector<string> V)
{
stack<double> S;
for(int i = 0; i < V.size(); i++)
{
if(V[i].length() == 1 && isOperate(V[i][0]))
{
double a = 0, b = 0;
if(!S.empty())
{
a = S.top();
S.pop();
}else return INT_MAX;
if(!S.empty())
{
b = S.top();
S.pop();
}else return INT_MAX;
switch(V[i][0])
{
case '+':
S.push(b+a);
break;
case '-':
S.push(b-a);
break;
case '*':
S.push(b*a);
break;
case '/':
S.push(b/a);
break;
default:
return INT_MAX;
}
}
else
{
if(scd(V[i]) == INT_MAX) return INT_MAX;
else S.push(scd(V[i]));
}
}
if(S.empty()) return INT_MAX;
double value = S.top();
S.pop();
return value;
}
calculator::~calculator()
{
}
运行结果:
点击C清除历史记录
以及报错处理
double scd(string s)
{
if(s.length() == 0) return INT_MAX;
bool flag = false;
for(int i = 0; i < s.length(); i++)
{
if(i == 0 && s[i] == '-') continue;
else if(s[i] == '.' && !flag)
{
if(i > 0 && isNum(s[i-1]))
{
flag = true;
continue;
}
else return INT_MAX;
}
else if(isNum(s[i])) continue;
else return INT_MAX;
}
double result = atof(s.c_str());
return result;
}
这段代码实现的是将一个字符串转化为 double 类型的数值。函数的参数是一个字符串类型的变量 s,表示需要转化的字符串。
函数首先检查字符串长度是否为0,如果是,则返回一个最大值为 INT_MAX 的数值。
然后,函数遍历字符串中的每一个字符,做如下判断:
-
如果字符是负号并且是第一个字符,则跳过该字符,继续检查下一个字符。
-
如果字符是小数点并且之前没有出现过小数点,则继续检查下一个字符。
-
如果字符是数字,则继续检查下一个字符。
-
如果字符不是上述三种情况,则字符串中包含非法字符,返回一个最大值为 INT_MAX 的数值。
如果字符串中没有非法字符,则函数使用 atof 函数将字符串转化为 double 类型的数值,并返回这个数值。
vector<string> midToPost(string s)
{
stack<char> S;
vector<string> V;
int i = 0;
while(i < s.length())
{
if(isNum(s[i]))
{
string str = "";
while(isNum(s[i]) || s[i] == '.')
{
str += s[i];
i++;
}
V.push_back(str);
}
else if(isOperate(s[i]))
{
if(s[i] == '-' && (i == 0 || !isNum(s[i-1])))
{
string str = "-"; i++;
while(isNum(s[i]) || s[i] == '.')
{
str += s[i]; i++;
}
V.push_back(str);
}
else
{
if(S.empty())
{
S.push(s[i]); i++;
}
else
{
int initial = level(s[i]);
if(initial == 2)
{
while(level(S.top()) != 5 && !s.empty())
{
string str = "";
str += S.top();
V.push_back(str);
S.pop();
}
if(S.top() == '(') S.pop();
i++;
}
else
{
while(!S.empty() && initial <= level(S.top()) && level(S.top()) != 5)
{
string str = "";
str += S.top();
V.push_back(str);
S.pop();
}
S.push(s[i]); i++;
}
}
}
}
else
{
cout << "表达式出错" << endl;
V.clear();
return V;
}
}
while(!S.empty())
{
string str = ""; str += S.top();
S.pop();
V.push_back(str);
}
//for(int i = 0; i < V.size(); i++) cout << V[i] << "[]";
return V;
}
这段代码实现了将中缀表达式转换为后缀表达式的功能。函数接受一个字符串 s,其中包含中缀表达式,返回一个字符串数组 vector<string>,其中为转换后的后缀表达式。
- 遍历字符串 s,如果遇到数字,将数字及其可能的小数点连续取出,放入 vector<string> V 中,表示该数字。
- 如果遇到运算符号,分为如下情况处理: a. 如果当前运算符是负号 "-",且它前面没有数字或者前面的字符不是数字或括号,则它是一个负数的符号,需要将其作为数字的一部分,连同负数后面的数字一起取出,放入 vector<string> V 中。 b. 如果当前运算符不是负号,需要考虑其与栈中已有运算符的优先级,如果栈顶运算符的优先级高于等于当前运算符,需要将栈顶运算符弹出,并放入 vector<string> V 中,直到栈顶元素优先级低于当前运算符或栈顶为左括号 "(",此时将当前运算符压入栈中。
- 如果遇到非数字和运算符的字符,说明表达式存在格式错误,直接返回空的 vector<string> V。
- 遍历结束后,如果栈中还有元素,需要将其弹出并放入 vector<string> V 中,得到最终的后缀表达式。
最后,程序返回 vector<string> V,其中包含转换后的后缀表达式。
double getValue(vector<string> V)
{
stack<double> S;
for(int i = 0; i < V.size(); i++)
{
if(V[i].length() == 1 && isOperate(V[i][0]))
{
double a = 0, b = 0;
if(!S.empty())
{
a = S.top();
S.pop();
}else return INT_MAX;
if(!S.empty())
{
b = S.top();
S.pop();
}else return INT_MAX;
switch(V[i][0])
{
case '+':
S.push(b+a);
break;
case '-':
S.push(b-a);
break;
case '*':
S.push(b*a);
break;
case '/':
S.push(b/a);
break;
default:
return INT_MAX;
}
}
else
{
if(scd(V[i]) == INT_MAX) return INT_MAX;
else S.push(scd(V[i]));
}
}
if(S.empty()) return INT_MAX;
double value = S.top();
S.pop();
return value;
}
从左往右遍历后缀表达式,如果遇到运算符,则从栈中取出上一个操作数(先取出的是第二个操作数,后取出的是第一个操作数),进行运算,并将结果压入栈中;如果遇到数字,则将其转化为 double 类型并压入栈中。如果在遍历过程中栈为空,则说明表达式有错误,返回 INT_MAX。
其中,isOperate 函数用于判断一个字符是否为运算符;scd 函数用于将一个字符串转化为数字,如果无法转化则返回 INT_MAX。如果遇到未知的运算符,也返回 INT_MAX。
最后,如果栈中只有一个元素,则为计算结果。将其取出并返回。如果栈中有多个元素,则说明表达式有错误,返回 INT_MAX。