- A+
由于eval()在安全性上存在问题,因此需考虑使用其余办法解决字符串表达式的计算。在数据结构中,栈(stack)是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据存入栈底,最后的数据存在栈顶。
中缀表达式是一种通用的逻辑或算术公式表达方法,操作符以中缀形式处于操作数之间。而后缀表达式则是将运算符放在两个操作数之后,严格按照从左向右的顺序进行执行。
我们可以利用一个字符栈将中缀表达式转化为后缀表达式,再利用数字栈计算,得到运算结果。
首先,需要规定运算符的优先级来判断进行出栈、入栈操作。通常,+、-运算符的优先级要低于/、*、%。
然后,我们定义两个数组optstack(操作符栈)、numstack(数字栈)分别用于存储不同的数据。
接下来,需要将字符串表达式转化为数组,可以规定每个字符按相同的分隔符隔离,以保证数据不会混淆。也可以利用利用递归判断,从而判断个位数、十位数....再利用循环判断每个数组元素的类型。
入栈、出栈需遵从以下规则:
①如果元素为数字,则直接将数字存入后缀表达式中
<?php if(is_numeric($s)) { $this->newstr .= $s.'|'; } ?>
②如果元素为左括号(“(”),则无条件入栈
③如果元素为右括号(“)”),则出栈,直至栈顶为左括号,并将左括号删除。
<?php if($s == ')') { while(($opt = array_pop($this->optstack))!='') { if($opt == '(')break; $this->newstr .= $opt.'|'; } } ?>
④如果为运算符,则需要判断运算符优先级,如果当前元素优先级高于栈顶,则入栈;若低于,则执行出栈操作。
<?php if(in_array($s,array('+','-','/','*','%'))&& count($this->optstack)>0) { $strpop = $this->optstack[count($this->optstack)-1]; if($this->level($s, $strpop)!=1) { for($j= count($this->optstack)-1;$j>=0;$j--) { if($this->optstack[$j]=='(') { break; } $this->newstr .= $this->optstack[$j].'|'; unset($this->optstack[$j]); } }else{ $this->optstack[] = $s; } } ?>
最后,利用数字栈运算后缀表达式。运算需遵从以下规则:
①如果元素为数字,则将数字直接入栈。
②如果元素为运算符,则将栈内的两个数字出栈,进行运算,再将结果入栈。
③栈顶(栈顶)即为运算结果。
<?php for($k = 0;$k<count($houzhi);$k++) { if(in_array($houzhi[$k], array('+','-','*','/','%'))) { $res = $this->yunsuan(array_pop($this->numstack),array_pop($this->numstack), $houzhi[$k]); $this->numstack[] = round($res,2); }else{ $this->numstack[] = $houzhi[$k]; } } if(count($this->numstack))$this->result = $this->numstack[0]; ?>