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-----完美结束。