简易计算器
项目完整代码:Calculator
界面
功能
- 实现带括号的四则运算、倒数、相反数功能;
- 实时计算;
- 括号计数,自动补全。
实现
思路
- 按下数字键或者合法的小数点对输入的文本进行追加,作为操作数;
- 按下右括号或者操作符后,将当前lineEdit中的值作为操作数压入栈中,对表达式进行计算后更新表达式;
- 按下
1/x
或者+/-
将lineEdit中的表达式作为操作数计算中间结果并显示,同时更新临时表达式。
使用两个栈(操作数栈numStk,操作符栈opStk)和一个队列(最内层括号的操作符tmpQue)实现带括号的计算(按下括号或者操作符后),具体算法流程如下:
- 如果当前符号(symbol)为(,直接入栈;
- 如果symbol为+、-、*、/,比较opStk栈顶元素与symbol:
- 如果opStk为空,symbol 直接入栈;
- 如果opStk栈顶元素为(,symbol 直接入栈;
- 如果opStk栈顶元素为*、/或者 symbol 为 +、-,进行计算,并重复第2步;
- 否则 symbol 直接入栈;
- 如果 symbol 是右括号 ),则不断弹出opStk的栈顶元素并加入tmpQue中,直到遇到栈顶元素为左括号(为止,且左括号(从栈弹出后不加入tmpQue中。从tmpQue队首取出操作符进行计算;
问题
为左括号(添加计数
1
2
3btnLabel=new QLabel(ui->lParButton);
// ...
btnLabel->setText(tr(" <sub>%1</sub>").arg(lParNum));1/x 和 +/- 的实现:
设计一个tmpStr作为临时操作数的表达式,以1/x为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22void MainWindow::pushRecButton()
{
// _input 只记录键入的操作数,lineEdit可能为中间结果
// 如果不清空,无法判断_input的内容为当前输入的内容还是上次输入的内容
_input.clear();
QString str = ui->lineEdit->text();
if(str.isEmpty()) return;
if(_tmpValStr.isEmpty() && ui->resLabel->text().endsWith(')')) return;
if(_tmpValStr.isEmpty())
{
_tmpValStr.append(str);
}
_tmpValStr = "1 / (" + _tmpValStr + ")";
double ret = 1 / str.toDouble();
ui->resLabel->setText(_exp + _tmpValStr); // 追加 tmpValStr 到 表达式exp
ui->lineEdit->setText(QString::number(ret));
}
简易计算器
https://ww1820.github.io/posts/67fe0e7e/