计算器中的“=”按钮这部分的代码解释
目录
一、代码部分
void Widget::on_equalButton_clicked()
{
QStack<int> s_num,s_opt; //声明两个int类型变量
char opt[128]={0};//char型数组
int i = 0,tmp = 0,num1,num2;//声明变量i,tmp,num1,num2
//把QString 转换成 char*
QByteArray ba;//字节数组
ba.append(expression);//把QString转换成QByteArray
strcpy(opt,ba.data());//data可以把QByteArray转换成char *
while(opt[i]!='\0'||s_opt.empty()!=true)//在字符串中'\0'用作字符串的结束标志,字符串没结束且不为空的情况下
{
if(opt[i]>='0'&&opt[i]<='9')//字符在0-9之间
{
tmp=tmp*10+opt[i]-'0';
i++;
if(opt[i]<'0'||opt[i]>'9')//字符不在0-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(num2+num1); //进栈
break;
case '-':
num1 = s_num.top();
s_num.pop();
num2 = s_num.top();
s_num.pop();
s_num.push(num2-num1); //进栈
break;
case '*':
num1 = s_num.top();
s_num.pop();
num2 = s_num.top();
s_num.pop();
s_num.push(num2*num1); //进栈
break;
case '/':
num1 = s_num.top();
s_num.pop();
num2 = s_num.top();
s_num.pop();
s_num.push(num2/num1); //进栈
break;
}
}
else //新增,解决2*3+7死循环时的问题
{
s_opt.push(opt[i]);
i++;
continue;
}
}
}
//最后留在栈里的就是结果,将结果显示
ui->mainLineEdit->setText(QString::number(s_num.top())); //QString中有个静态成员函数number(),可以把数字转换成字符串。
expression.clear();
}
int Widget::Priority(char ch)
{
switch (ch)
{
case '(':
return 3;
case '*':
case '/':
return 2;
case '+':
case '-':
return 1;
default:
return 0;
}
}
pop()删除栈顶元素
top() 是取出栈顶元素,不会删掉栈里边的元素
二、解释
这里有个优先级函数不好理解
三个并列的条件语句:
条件1:if(s_opt.empty() == true || Priority(opt[i]) > Priority(s_opt.top()) ||
(s_opt.top() == '(' && opt[i] != ')'))
//如果操作符s_opt是空,或者当前操作符的优先级Priority大于栈顶的优先级,或者栈顶的操作符 是‘(’ 不是 ')' 然后把操作符入栈
条件2:if(s_opt.top() == '(' && opt[i] == ')')
//如果操作符是 ‘(’ 不是 ')' 直接操作符删除
条件3:if (Priority(opt[i]) <= Priority(s_opt.top() || (opt[i] == ')' && s_opt.top()) ||
(opt[i]) == '\0' && s_opt.empty() != true))
//如果当前的操作符小于栈顶操作符,或者操作符是(且位于栈顶,或者操作符不是字符尾和不是空时 计算+-*/
例如(3-1)+1
- ‘(’ 满足条件1的s_opt.empty() == true ,刚开始时s_opt未存入任何操作符,s_opt现在有‘(’
- ‘-’满足条件1的(s_opt.top() == '(' && opt[i] != ')'),s_opt.top()=='('且不等于‘)’
- ')’满足条件3的(Priority(opt[i]) <= Priority(s_opt.top() ,Priority(opt[i])是‘)’的优先级0,Priority(s_opt.top())是‘-’号的优先级1,0<1所有满足条件3,计算3-1,结果保存在s_num=2
- ')’满足条件2,删除s_opt里面的操作符
- ‘+’满足条件1的s_opt.empty() == true,每次计算都会pop删除栈顶的操作符,所有s_opt此时为0,之前存入的操作符已经被删除完
- ‘+’满足条件3的(Priority(opt[i]) <= Priority(s_opt.top(),Priority(opt[i])是当i=7时的第七个字符‘\0’的优先级是0,Priority(s_opt.top())是‘+’号的优先级1,0<1所有满足条件3,计算2+1=3,结果继续入栈存入s_num中
三、思路
思路理解:
条件1是存入操作符
条件2在s_opt栈顶是'('和当前操作符是‘)’时删除s_opt栈顶操作符
条件3判断操作符优先级,当前操作符 优先级 小于 栈顶优先级时进行计算
四、死循环!
出现问题:运行2*3+7的时候报错!
产生原因:i无法正常加1,一直在i=3时循环
解决方法:
else //新增,解决2*3+7死循环时的问题 { s_opt.push(opt[i]); i++; continue; }
完整代码参考博客和哔站QT基础教程: