具备优先级的加、减、乘、除和括号功能的完整程序代码如下:
void myframewindow::OpKeys(UINT key)
{
if(mark==1) return; //出错后返回,屏蔽操作符的操作
if(flag==1) flagchar=0; //flag=1,表示操作数已更新
switch(key)
{
case CM_KEYADD:
op=ADD; opc='+'; flagchar ^=1; //flagchar=1,第一次按操作符
break; //op,操作符的优先数
case CM_KEYSUB:
op=SUB; opc='-'; flagchar ^=1;
break;
case CM_KEYMUL:
op=MUL; opc='*'; flagchar ^=1;
break;
case CM_KEYDIV:
op=DIV; opc='/'; flagchar ^=1;
break;
case CM_KEYEQU:
op=EQU; opc='='; flagchar ^=1;
break;
case CM_KEYLPARE:
op=LPARENT; opc='(';
break;
case CM_KEYRPARE:
op=RPARENT; opc=')';
break;
}
if(opc=='('){ flagparent++; //左括号进栈并显示,并限制层数为6
if(flagparent>6) { flagparent=6;
PAR.SetWindowText(stringpar[flagparent]); return; }
else { PAR.SetWindowText(stringpar[flagparent]); pushchar(opc);
topop--; pushop(op); flag=0; return; }
}
if(flag==1){ push(REG); flag=0; REG=0; shift=1; } //是操作数,可压栈
if(opc=='='&&flagchar==0) {flagchar=1; return;} //多次按压等号,显示值不变
loop:
if(opc=='='&&topop==0) //操作符是等号并且操作符栈空,显示最终运算结果
{ result=stack[top];DoDisplay(result); flag=0; flagchar=0; }
else if(opc=='+'||opc=='-'||opc=='*'||opc=='/'||opc=='=') //如果是操作符
if(op>opstack[topop]||flagchar==0) //当前操作符优先数>栈顶操作符优先数或操作符栈空,真
{ if(flagchar==1)
{ pushchar(opc); topop--; pushop(op); flagchar=1; } //flagchar=1,操作符进栈
else
{ stackchar[topop]=opc; opstack[topop]=op; flagchar=1; } //更改操作符栈中的操作符
}
else //假,出栈两个操作数,一个操作符,运算结果压栈
{ operand1=pop(); operand2=pop(); opmark=popchar();
topop++; ops=popop();
if(mark==1) return;
switch(opmark)
{
case '+': push(operand2+operand1); break;
case '-': push(operand2-operand1); break;
case '*': push(operand2*operand1); break;
case '/': if(operand1==0) //除数为0,报错;并清操作数栈和操作符栈,设置错误标记mark=1
{ shift=1; REG=0; LCD.SetWindowText("E"); //显示错误标记 E
top=-1; topop=0; mark=1; return; }
else
push(operand2/operand1);
break;
}
result=stack[top]; DoDisplay(result); //显示中间运算结果
if (opc=='=' || (op==1 && op==opstack[topop])) {flag=0; flagchar=1; goto loop; }
else {pushchar(opc); topop--; pushop(op); flagchar=1; flag=0; return;}
//如果是等号或(+或-),侧循环执行;其它情况则操作符压栈
}
else if(opc==')') //栈顶是左括号,则出栈;否则,出栈两个操作数,一个操作符,运算后压栈
{ loop1: if(stackchar[topop]=='('){ popchar(); topop++; popop(); flagparent--;
PAR.SetWindowText(stringpar[flagparent]); return; }
else if(stackchar[topop]!='(')
{ if(flagparent==0) return;
operand1=pop(); operand2=pop(); opmark=popchar();
topop++; ops=popop();
if(mark==1) return;
switch(opmark)
{
case '+': push(operand2+operand1); break;
case '-': push(operand2-operand1); break;
case '*': push(operand2*operand1); break;
case '/': if(operand1==0)
{ shift=1; REG=0; LCD.SetWindowText("E");
top=-1; topop=0; mark=1; return; }
else
push(operand2/operand1);
break;
}
result=stack[top]; DoDisplay(result); flag=0; flagchar=0;
goto loop1; //循环执行直到遇到左括号为止,否则出错处理
}
}
}
二、程序实例
具备优先级的加、减、乘、除和括号功能的计算器的运行效果见图2,经在Windows XP环境下对多个计算表达式进行测试,计算结果正确。在此基础上如增加各种函数功能,即可成为非常实用的科学计算器。
图2 计算器
|