#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("计算器"); //命名对话框
QFont f("宋体",10); //字体对象
ui->outputLineEdit->setFont(f);
//删除按钮上放图片
QIcon con("C:\\Users\\apple\\Desktop\\QtProject\\QtOnline\\calculator\\del.PNG");
ui->delButton->setIcon(con);
//连接信号与槽 四个参数分别是:谁发出信号 发出什么信号 谁处理信号 怎么处理信号
//若槽函数处理的信息量小 可采用内联格式书写
connect(ui->addButton,&QPushButton::clicked,[this]()//点击加号
{
expression += "+"; //字符串末尾添加一个字符“+”
ui->outputLineEdit->setText(expression); //在输出框中显示算式字符串
});
connect(ui->subButton,&QPushButton::clicked,[this]()//点击减号
{
expression += "-";
ui->outputLineEdit->setText(expression);
});
connect(ui->mulButton,&QPushButton::clicked,[this]()//点击乘号
{
expression += "*";
ui->outputLineEdit->setText(expression);
});
connect(ui->divButton,&QPushButton::clicked,[this]()//点击除号
{
expression += "/";
ui->outputLineEdit->setText(expression);
});
//改变等号按钮背景颜色
ui->equalButton->setStyleSheet("background:pink");
}
Widget::~Widget() //析构函数
{
delete ui;
}
void Widget::on_oneButton_clicked()//点击1
{
expression += "1";
ui->outputLineEdit->setText(expression);
}
void Widget::on_twoButton_clicked()//点击2
{
expression += "2";
ui->outputLineEdit->setText(expression);
}
void Widget::on_threeButton_clicked()//点击3
{
expression += "3";
ui->outputLineEdit->setText(expression);
}
void Widget::on_fourButton_clicked()//点击4
{
expression += "4";
ui->outputLineEdit->setText(expression);
}
void Widget::on_fiveButton_clicked()//点击5
{
expression += "5";
ui->outputLineEdit->setText(expression);
}
void Widget::on_sixButton_clicked()//点击6
{
expression += "6";
ui->outputLineEdit->setText(expression);
}
void Widget::on_sevenButton_clicked()//点击7
{
expression += "7";
ui->outputLineEdit->setText(expression);
}
void Widget::on_eightButton_clicked()//点击8
{
expression += "8";
ui->outputLineEdit->setText(expression);
}
void Widget::on_nineButton_clicked()//点击9
{
expression += "9";
ui->outputLineEdit->setText(expression);
}
void Widget::on_zeroButton_clicked()//点击0
{
expression += "0";
ui->outputLineEdit->setText(expression);
}
void Widget::on_leftButton_clicked()//点击左括号
{
expression += "(";
ui->outputLineEdit->setText(expression);
}
void Widget::on_rightButton_clicked()//点击右括号
{
expression += ")";
ui->outputLineEdit->setText(expression);
}
void Widget::on_clearButton_clicked()//清空显示框
{
expression.clear(); //字符串清空函数
ui->outputLineEdit->clear(); //清空运行框内容
}
void Widget::on_delButton_clicked()//点击删除按键
{
expression.chop(1); //将字符串最后的一个元素删除
ui->outputLineEdit->setText(expression);
}
int Widget::Priority(char ch) //定义运算符优先级 右括号不入栈版
{
switch (ch)
{
case'+':
case'-':
return 1;
case'*':
case'/':
return 2;
case'(':
return 3;
default:
return 0;
}
}
void Widget::on_equalButton_clicked() //点击等号时
{
QStack<int> s_num,s_opt; //开两个int型栈 数值栈s_num 符号栈s_opt
char opt[128] = {0};
int i = 0 , tmp = 0 , num1 , num2; //遍历指针i 操作数num1 操作数num2
//把QString转换成char *
QByteArray ba;
ba = expression.toUtf8(); //把QString转换成QByteArray
// ba.append(expression);
strcpy(opt,ba.data()); //data把QByteArray转换成const char *
//栈操作
while (opt[i] != '\0' || s_opt.empty() != true) //字符串未读完或符号栈非空
{
if(opt[i] >= '0' && opt[i] <= '9') //遇到数字
{
tmp = tmp * 10 +opt[i] - '0'; //将多个char型数组元素转成一个int型数据
i++;
if(opt[i] < '0' || opt[i] >'9') //一个数据接收结束 压栈
{
s_num.push(tmp);
tmp = 0;
}
}
else //遇到操作符
{
if(s_opt.empty() == true || Priority(opt[i])>Priority (s_opt.top()) ||(s_opt.top()=='('&& opt[i] != ')'))
//符号栈为空 或 当前读取元素的优先级高于符号栈栈顶元素优先级 或 *多重括号嵌套情况* 即符号栈栈顶为‘(’且当前不为‘)’
//后压栈的操作符先参与计算。所以当前运算符优先级比栈顶元素高时则压栈,括号未匹配时压栈。
//符号栈为空:第一次遇到运算符 & 式子前面的括号运算全部结束后读取最后一个运算符
{
s_opt.push(opt[i]); //当前元素压进符号栈
i++;
continue;
}
if(s_opt.top() == '(' && opt[i] == ')')
//符号栈栈顶为‘(’且当前为‘)’
//因为计算之后运算符就退栈了,所以当前情况为括号中运算符全部执行结束
//注意此时右括号不压栈 仅执行左括号退栈
{
s_opt.pop(); //符号栈栈顶弹出 将左括号退栈
i++; //右括号不压栈 直接向后读取字符串下一位
continue;
}
if(Priority(opt[i]) <= Priority (s_opt.top()) ||(opt[i] == ')' && s_opt.top() != '(' ) ||(opt[i] == '\0' && s_opt.empty() != true))
{
//当前元素优先级不大于符号栈栈顶优先级 或 当前为‘)’且符号栈栈顶不为‘(’ 或 字符串读取结束且符号栈不为空
//多重括号嵌套在第一步已进行判断。所以此步骤为算式前部分需要比后部分先计算的情况 & 括号匹配后执行括号内计算
//字符串读取结束且符号栈不为空情况是最后一步 此时数值栈剩余两个元素 符号栈剩余一个元素
char ch = s_opt.top();
s_opt.pop();
switch(ch)
{
case '+':
num1 = s_num.top();
s_num.pop();
num2 = s_num.top();
s_num.pop();
s_num.push(num1 + num2);
break;
case '-':
num1 = s_num.top();
s_num.pop();
num2 = s_num.top();
s_num.pop();
s_num.push(num2 - num1); //注意减数与被减数顺序 num2后出栈 在算式中在num1前方
break;
case '*':
num1 = s_num.top();
s_num.pop();
num2 = s_num.top();
s_num.pop();
s_num.push(num1 * num2);
break;
case '/':
num1 = s_num.top();