利用教材中所给的算符优先关系,实现算术四则运算表达式的求值;由于计算表达式的值的过程中需要知道整个表达式,所以我们需要一个容器储存数据(分为数字和字符两类数据),鉴于对表达式求值时的步骤,使用栈来存储是最合适的。但是在第一次实现后存在严重的问题,由于对数字数据的操作是通过字符类型(char)来存储的,未经过转换,会导致连续的两个数分批存入栈中,导致出现bug;因此需要通过转换使数字栈中存入真正数字(int,float等)类数据。
我对输入的连续的两个及两个以上字符类(char)数字去转换为数字数据的操作函数INTcheng(),以及数字中转栈暂时存储数字数据,通过三个栈(数字(int),计算符号(char)及数字中转站(char))修改了只能执行一位数字运算的bug。
typedef int Status;//函数返回值
typedef int ElemType;//数据类型(int)
一、使用到的数据结构
stack<char> OPTR;//字符串栈
stack<int> OPND;//数字栈
stack<char> OPNDbe;//数字中转站
两个字符栈用来直接接收数据,一个数字栈存放数字中转站转换为整型的数据
二、教材中给出的优先级数据输入与判断优先级
1.优先级列表的输入(利用二维数组)
char contrast[7][7]={'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=',' ',
'>','>','>','>',' ','>','>',
'<','<','<','<','<',' ','<'};//字符串储存比较结果
由于教材中优先级是通过表存储的,因此在这里直接使用二维数组记录优先级比较结果
2.优先级数据的利用
//比较运算符优先级-------------------------------------------------------
char Precede(char a,char ch){
int i,j;//计数器
switch(a){//每个符号对应的数据
case '+':
i=0;break;
case '-':
i=1;break;
case '*':
i=2;break;
case '/':
i=3;break;
case '(':
i=4;break;
case ')':
i=5;break;
case '#':
i=6;break;
}
switch(ch){//每个符号对应的数据
case '+':
j=0;break;
case '-':
j=1;break;
case '*':
j=2;break;
case '/':
j=3;break;
case '(':
j=4;break;
case ')':
j=5;break;
case '#':
j=6;break;
}
return contrast[i][j];//返回比较值
}
利用二维数组记录所有比较结果,比较两运算符号优先级时用编号代替,最终在二维数组中寻找结果。
二、主函数
int main()
{
int resurt=Eva();
//cout<<resurt<<endl;
//cout<<Operate('3','*','5')<<endl;
printf("%d",resurt);//输出答案
}
只应用到了Eva()计算函数,其他操作在计算函数中执行。
三、计算函数
//计算-------------------------------------------------------------
int Eva(){
OPTR.push('#'); //起始符号“#”压入栈
char ch,theta,x;
int a,b;
cin>>ch;//首个输入
while(ch!='#'|| OPTR.top() !='#'){//表达式还未读完/栈顶元素不为“#”
if(!In(ch)){
OPNDbe.push(ch);
cin>>ch;
}//不是运算符入OPND栈
else{
OPND.push(INTcheng());//转换为数字的数据入栈
switch(Precede(OPTR.top(),ch))
{
case'<':
OPTR.push(ch);cin>>ch;
break;
case'>':
theta=OPTR.top();
OPTR.pop();
b=OPND.top();
OPND.pop();
a=OPND.top();
OPND.pop();//提取a,ch,b
OPND.push(Operate(a,theta,b));//执行a ch b 操作
cout<<OPND.top()<<endl;
break;
case'=':
x=OPTR.top();
OPTR.pop();
cin>>ch;
break;
}
}
}
return OPND.top();
}
其中包括(1)、输入数据(输入时的数据全部为字符类char数据),(2)、引用In()函数判断输入数据应该压入字符栈还是数字中转站,(3)、引用INTchage()函数,使中转站的数据转换为整型数据压入数字栈中,(4)、通过比较运算符优先级函数Precede()判断是否执行运算
四、In()函数判断输入数据输入类型
Status In(char ch){
if(ch<=57&&ch>=48)//ASCII表对应数字字符范围
return ERROR;
else
return OK;
}
五、INTchage()函数转换数字中转站的数据为整形并压入数字栈
int INTcheng(){//字符型数字向整型数字转换
int i=1;//记录个十百位数
int add;
int sum=OPNDbe.top()-'0';
cout<<sum<<endl;
OPNDbe.pop();
while(!OPNDbe.empty()){
add=OPNDbe.top()-'0';
cout<<add<<endl;
for(int j=0;j<i;j++){
add*=10;
}
sum+=add;
OPNDbe.pop();
i++;
}
return sum;
}
六、主要改进操作:
相较于教材上给的代码,这里新增了一个数字中转站,使数据可以通过int类型传输与计算,而不是字符类型数据计算,修复了无法计算多位数运算的bug,主要实现函数为INTchage();
以下为INTchage()函数实现;
#include <iostream>
#include <stack>
#include <queue>
using namespace std;stack<char> OPNDbe;//数字中转站
int INTcheng(){//字符型数字向整型数字转换
int i=1;//记录个十百位数
int add;
int sum=OPNDbe.top()-'0';
cout<<sum<<endl;
OPNDbe.pop();
while(!OPNDbe.empty()){
add=OPNDbe.top()-'0';
cout<<add<<endl;
for(int j=0;j<i;j++){
add*=10;
}
sum+=add;
OPNDbe.pop();
i++;
}
return sum;
}int main()
{
OPNDbe.push('1');OPNDbe.push('3');OPNDbe.push('2');
int resut=INTcheng();
cout<<resut;
}
通过结果为132可知转换成功,稍作修改使其结果可在输入过程中压入数字栈即可实现表达式求值的改进。