转化为后缀表达式方便计算(所有的计算按运算符出现的顺序,严格从左向右进行,不再考虑运算符的优先规则。)。
( |
然后是数字2 直接输出 2
接着是+号,进栈
+ |
( |
然后是数字1 直接输出在2后面 2 1
然后遇到右括号,栈中所有元素出栈,输出加号,左括号不输出 2 1 +
接着*号,进栈
* |
然后是数字3 直接输出 2 1 + 3
表达式结束,栈中元素出栈 输出号 2 1 + 3
QStack stack;
QString temp;//数字输出
QStringList list;//全部输出
while(!expression.isEmpty())
{
if(expression.startsWith('+')||expression.startsWith('-')||expression.startsWith('*')||expression.startsWith('/')||expression.startsWith('(')||expression.startsWith(')'))
{
//遇到运算符及左右括号,可能进栈,出栈
if(!temp.isEmpty())
{
list.append(temp);
temp.clear();
}
//+-)优先级高于或等于其它运算符及左括号,遇到则使栈中元素弹出
if(expression.startsWith('+')||expression.startsWith('-')||expression.startsWith(')'))
{
while(!stack.isEmpty())
{
if(stack.top()==QString('('))
{
//栈顶为左括号,遇到右括号,直接让左括号出栈,不输出
if(expression.startsWith(')'))
{
stack.pop();
}
break;
}
else
{
//将栈中元素输出,直到栈顶为左括号
list.append(stack.pop());
}
}
}
if(expression.startsWith(')'))
expression.remove(0,1);
if(!expression.isEmpty())
{
stack.push(expression.left(1));
expression.remove(0,1);
}
}
else
{
//遇到数字,直接输出
temp+=expression.left(1);
expression.remove(0,1);
}
}
if(!temp.isEmpty())
list.append(temp);
while(!stack.isEmpty())
{
list.append(stack.pop());
}
现在按规则计算后缀表达式 2 1 + 3 *
遇到数字2 进栈
2 |
遇到数字1 进栈
1 |
2 |
遇到+号 将处于栈顶的两个数字 1 2 出栈 进行加法运算 得结果为3 进栈
3 |
遇到数字3 进栈
3 |
3 |
遇到乘号* 将处于栈顶的两个数字3 3 进行乘法运算 得结果为9 结束。
QString operand1;
QString operand2;
QString result;
int row=0;
while(!list.isEmpty())
{
if(list.startsWith("+"))
{
operand2 = stack.pop();
operand1 = stack.pop();
result = QString::number(operand1.toDouble()+operand2.toDouble());
stack.push(result);
}
else if(list.startsWith("-"))
{
operand2 = stack.pop();
operand1 = stack.pop();
result = QString::number(operand1.toDouble()-operand2.toDouble());
stack.push(result);
}
else if(list.startsWith("*"))
{
operand2 = stack.pop();
operand1 = stack.pop();
result = QString::number(operand1.toDouble()*operand2.toDouble());
stack.push(result);
}
else if(list.startsWith("/"))
{
operand2 = stack.pop();
if(operand2.toDouble()==0)
{
lineEdit->setText(trUtf8("除数不能为0"));
flag = true;
}
operand1 = stack.pop();
result = QString::number(operand1.toDouble()/operand2.toDouble());
stack.push(result);
}
else
{
stack.push(list.first());
}
list.removeFirst();
operand1.clear();
operand2.clear();
}
for(int i=0;i<10;i++)
{
digitButtons[i]=createButtons(QString::number(i));
digitButtons[i]->setStyleSheet("font-size:30px;color:white;background-color:rgb(71,71,71)");
//QPalette pal = digitButtons[i]->palette();
//pal.setColor(QPalette::Button,QColor(112,128,105));
//pal.setColor(QPalette::ButtonText,QColor(225,225,225));
//digitButtons[i]->setPalette(pal);
}
symbolButtons[0]=createButtons("*");
symbolButtons[1]=createButtons("/");
symbolButtons[2]=createButtons("+");
symbolButtons[3]=createButtons("-");
symbolButtons[4]=createButtons(".");
symbolButtons[5]=createButtons("=");
symbolButtons[6]=createButtons("(");
symbolButtons[7]=createButtons(")");
symbolButtons[8]=createButtons(trUtf8("删除"));
for(int i=0;i<8;i++)
{
symbolButtons[i]->setStyleSheet("font-weight:bold;font-size:30px;color:white;background-color:rgb(33,33,33)");
}
symbolButtons[8]->setStyleSheet("font-size:20px;color:white;background-color:rgb(26,26,26)");
一开始我是这么写的,看了一下觉得还可以再优化一下,就成了下面这样
QString buttonText[8] = {"*","/","+","-",".","=","(",")"};
for(int i=0;i<8;i++)
{
symbolButtons[i]=createButtons(buttonText[i]);
symbolButtons[i]->setStyleSheet("font-weight:bold;font-size:30px;color:white;background-color:rgb(33,33,33)");
}
symbolButtons[8]=createButtons(trUtf8("删除"));
symbolButtons[8]->setStyleSheet("font-size:20px;color:white;background-color:rgb(26,26,26)");
下面是createButtons函数及buttonClicked函数
QToolButton *MainWindow::createButtons(const QString &text)
{
QToolButton *tb = new QToolButton;
tb->setText(text);
connect(tb,SIGNAL(clicked()),this,SLOT(buttonClicked()));
tb->setFixedSize(60,83);
if(text == QString("0"))
rightLayout->addWidget(tb,4,1);
else if(text == QString("("))
rightLayout->addWidget(tb,0,0);
else if(text == QString(")"))
rightLayout->addWidget(tb,0,1);
else if(text == QString(trUtf8("删除")))
rightLayout->addWidget(tb,0,3);
else if(text == QString("*"))
rightLayout->addWidget(tb,1,3);
else if(text == QString("/"))
rightLayout->addWidget(tb,2,3);
else if(text == QString("+"))
rightLayout->addWidget(tb,3,3);
else if(text == QString("-"))
rightLayout->addWidget(tb,4,3);
else if(text == QString("."))
rightLayout->addWidget(tb,4,0);
else if(text == QString("="))
rightLayout->addWidget(tb,4,2);
else
rightLayout->addWidget(tb,(text.toInt()-1)/3+1,(text.toInt()-1)%3);
return tb;
}
void MainWindow::buttonClicked()
{
if(flag == true)
{
lineEdit->clear();
flag = false;
}
QString expression = lineEdit->text();
QToolButton *tb = qobject_cast*>(sender());
QString text = tb->text();
if(text == QString(trUtf8("删除")))
lineEdit->backspace();
else if(text == QString("("))
{
lineEdit->cursorBackward(true);
QString leftLetter = lineEdit->selectedText();
if(leftLetter == QString("*")||leftLetter == QString("/")||leftLetter == QString("+")||leftLetter == QString("-"))
lineEdit->setText(expression+=text);
else
{
lineEdit->setText(expression);
return;
}
}
else if(text == QString(")"))
{
lineEdit->cursorBackward(true);
QString leftLetter = lineEdit->selectedText();
int countLeft=expression.count("(");
int countRight=expression.count(")");
if(leftLetter == QString("*")||leftLetter == QString("/")||leftLetter == QString("+")||leftLetter == QString("-")||leftLetter == QString(".")||leftLetter == QString("(")||countLeft<=countRight)
lineEdit->setText(expression);
else
lineEdit->setText(expression+=text);
}
else if(text == QString("*")||text == QString("/")||text == QString("+")||text == QString("-")||text == QString("."))
{
lineEdit->cursorBackward(true);
QString leftLetter = lineEdit->selectedText();
if(leftLetter == QString("*")||leftLetter == QString("/")||leftLetter == QString("+")||leftLetter == QString("-")||leftLetter == QString(".")|| leftLetter.isEmpty() )
{
lineEdit->setText(expression);
return;
}
else
lineEdit->setText(expression+=text);
}
else if(text == QString("="))
calculate();
else
lineEdit->setText(expression+=text);
}
计算器输入框选用QLineEdit类来实现,可以用键盘输入表达式,不过为了防止用户输入错误的信息,通过正则表达式来限制输入的内容只能为数字,小数点,加减乘除号和括号,而字母和其它符号将通通不被接受,不予输入!
QRegExp regExp("[0-9+*/()-.]*");
QRegExpValidator *validator =new QRegExpValidator(regExp,this);
lineEdit->setValidator(validator);
输入表达式,包含三位数,小数,加减乘除,括号
点击图中红色标注 等号 进行运算。
红色标注输入框显示运算结果。
红色标注显示框为计算过程。
点击红色框框标注的切换按钮切换显示栈中数据变化情况
红色框框标注显示栈中数据变化情况,上下两图分别为中缀表达式转后缀表达式和后缀表达式运算时的栈中数据变化情况。
源码已上传请点击 CSDN资源或Github下载