P53 页 表达式求值----请先查看相应书籍,至少先了解下p53页的算符间优先关系表。

算法3.4 : 描述“算符优先算法”的求值过程

表达式原文

OperandType EvaluateExpression(){

//算术表达式求值的算符优先算法。设OPTN和OPND分别为运算符栈和运算数栈

//OP为运算符集合

InitStack(OPTR); Push(OPTR,’#’);

initStack(OPND); c = getchar();

while (c != ‘#’ || GetTop(OPTR) != ‘#’){

if(! In(c,OP)){Push(OPND,c); c = getchar();}

else

switch (Precede(GetTop(OPTR),c)){

case ‘<’ : //栈顶元素优先权低

Push(OPTR,c); c = getchar();

break;

case ‘=’ : //脱括号并接收下一字符

Pop(OPTR,x); c = getchar();

Break;

Case ‘>’ : //退栈并将运算结果入栈

Pop(OPTR,theta);

Pop(OPND,b);

Pop(OPND,a);

Push(OPND,Operate(a,theta,b);

Break;

}//switch

}//while

Return Gettop(OPND);

}//EvaluateExpression

语句分析

OperandType EvaluateExpression(){

//算术表达式求值的算符优先算法。设OPTN和OPND分别为运算符栈和运算数栈

//OP为运算符集合

InitStack(OPTR); //初始化OPTR栈

Push(OPTR,’#’); //将“#”放入到OPTR栈的栈底

initStack(OPND); //初始化OPND栈

c = getchar(); //获取一个从键盘输入的字符

//接下来的代码将处理这个字符

while (c != ‘#’ || GetTop(OPTR) != ‘#’){

//只要c(从键盘获取的字符)不等于“#“ 或者从OPTR获取的栈顶元素不是”#“时,就一直循环。|| 逻辑运算符,只要有一个为真就为真,所以只要有一个遇到了#就会退出循环。

if(! In(c,OP)){Push(OPND,c);

//如果 c这个字符在OP这个集合中不存在。就是判断c是不是输入的运算符。如果不是去处符,则将c的字符入栈到OPND栈中去。

c = getchar();}

//然后再提示用户输入下一个字符

else

//否则的话,c就是OP集合中,说明c是个运算符

switch (Precede(GetTop(OPTR),c)){

//precede 应该是一个优先级比较的函数,将GetTop(OPTR)从OPTR的栈顶元素获取到的去处符与c进行比较优先级。

case ‘<’ : //栈顶元素优先权低

Push(OPTR,c);

c = getchar();

break;

//如果是栈顶元素的优先级低,则将输入的c入栈到OPTR栈,并再接收下一个字符

case ‘=’ : //脱括号并接收下一字符

Pop(OPTR,x);

c = getchar();

Break;

//如果两个运算符优先级相等的时候,也就是要么是左右括号匹配了,要么是#匹配了,但是这里不可能是#号,因为不是#是进入这个循环的条件。

Case ‘>’ : //退栈并将运算结果入栈

Pop(OPTR,theta);

Pop(OPND,b);

Pop(OPND,a);

Push(OPND,Operate(a,theta,b);

Break;

//如果是栈内的优先级大于获取的运算符,则先处理栈内的运算符。也就是先将栈顶的元素出栈后先进行运算,然后将结果入到栈内去。

}//switch

}//while

Return Gettop(OPND);

}//EvaluateExpression


分步骤分析:

4+2*3-10/5

第一步:判断4是否是运算符,不是运算符,则4入OPND栈,并获取下一个字符

第二步:+号与OPTR栈内的top元素比较优先级,top元素是一个#号,+号的优先级大于#号(任何运算符的运算优先级都大于#号,只有#自己与自己相等),+号入OPTR栈,并获取下一个字符

第三步:判断2是否是运算符,不是运算符,2入OPND栈,并获取下一个字符,

第四步::获取到的一个字符为“*“乘号。与OPTR栈顶的元素+号进行比较优先级,乘号优先,所以乘号直接入OPTR栈,然后获取下一个元素。

第五步:获取到的下一个元素是3,是一个操作数,不是运算符,所以直接入栈。再获取下一个元素。

第六步:获取到的元素为-号,-号与OPTR栈顶元素进行比较,是个乘号,所以乘号优先。

从OPTR栈中,乘号出栈

从OPND中,出栈两个OPND的数,一个是栈顶元素3,另外一个是次栈顶元素2.

先进行计算,3*2=6

将6入到OPND栈

获取下一个元素

第七步:获取到的下一个元素为-号,-号与栈顶元素进行比较,是个+号,栈里的元素是1,输出的符号为2,+与-号,谁在栈内谁优先。所以得先把栈内的算完,明细如下:

从OPTR中出栈+号

从OPND中出栈两个数,1个为上一步算出来的6,另外一个为4

进行计算,6+4=10

将10这个元素入栈到OPND栈中去

获取下一个元素

第八步:获取的元素为10,是一个操作数,数直接入栈到OPND栈中去,获取下一个元素

第九步:获取到的下一个元素为为/,与OPTR栈顶元素进行对比。/号优先,所以直接入栈到OPTR栈中去。获取下一个元素。

第十步:下一个元素为5,5是一个操作数,直接入栈到OPND栈中去,获取下一个元素。

第十一步:此时表示式已经完了,所以下一个输入的字符为“#“号。而#号遇到任何其它运算符都是低优先级的,所以此时的OPTR的栈顶元素为/,/的优先级大于#号的优先级,所以操作步骤如下:

从OPTR中出栈一个运算符/

从OPND中出栈两个数,一个是10,一个为5

10/5=2

将运算的结果2入栈到OPND中去。

获取下一个字符

第十二步:又是#号,再操作一遍

10-2=8

8入栈

第十三步:又是#号,再拉取栈顶元素,而此是的栈顶元素已经是#号了,所以此是循环结束

第十四步:return OPND的栈顶元素为8-----完美结束。