【栈】实现高级计算器

来源:互联网 发布:telnet 端口发送数据 编辑:程序博客网 时间:2024/05/19 11:46

实现一个计算器

9+2*8-2

30+2*6-1

7*2-3*5-2

实现思路:

1、程序扫描表达式

2、发现是数字就入数字栈(这里要特别注意,当数字不是一位的情况

3.如果发现是运算符

       a)如果符号栈为空,就直接入符号栈 

        b)如何符号栈,不为空,就判断

              I)   如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈.然后把当前符号入栈

                     这里要特别注意比如13-11-2的例子!当两个减号优先级相同时,如果不把已有的减号计算,就会计算成先计算11-2再用13-9=4的错误答案。所以这个地方是个while循环。

              II)   如果当前运算符的优先级大于符号栈顶的这个运算符的优先级,就入栈.

 

4、最后把所有的数都出栈,计算,留在数栈中的值就是最后结果


<html><head><meta http-equiv='content-type' content='text/html;charset=gbk'/></head><?php//$exp=$_GET['exp'];//$exp='9+2*8-3'; //[人眼睛3+12-2 =>15-2=>13]// $exp='304+10*6-10';   $exp='71*2-50*3-3-67*6+80';//-333 $numsStack=new MyStack();$operStack=new MyStack();$keepNum='';//专门用于拼接数字$index=0;//$index就是一个扫描标记while(true){//依次取出字符$ch=substr($exp,$index,1);//判断$ch是不是一个运算符if($operStack->isOper($ch)==TRUE){//是运算符/***/if($operStack->isEmpty()){$operStack->push($ch);}else{/*//需要一个函数来获取运算符的优先级 *和/的优先级为1 ,+和-为0$chPRI=$operStack->PRI($ch);$stackPRI=$operStack->PRI($operStack->getTop());if($chPRI<=$stackPRI){//从数栈依次出栈两个数$num1=$numsStack->pop();$num2=$numsStack->pop();//再从符号栈取出一个运算符$oper=$operStack->pop();//这里还需要一个计算的函数$res=$operStack->getResult($num1,$num2,$oper);//把$res入数栈$numsStack->push($res);//把当前这个符号再入符号栈 ?????这里是有问题的,一会儿再来解决$operStack->push($ch);}else{$operStack->push($ch);}*/while(!$operStack->isEmpty()&&$operStack->PRI($ch)<=$operStack->PRI($operStack->getTop())){//从数栈依次出栈两个数$num1=$numsStack->pop();$num2=$numsStack->pop();//再从符号栈取出一个运算符$oper=$operStack->pop();//这里还需要一个计算的函数$res=$operStack->getResult($num1,$num2,$oper);//把$res入数栈$numsStack->push($res);//把当前这个符号再入符号栈 ?????这里是有问题的,一会儿再来解决}$operStack->push($ch);}}else{//是数字$keepNum.=$ch;//先判断是否已经到了字符串的最后,如果已经到最后了,就直接入栈//判断一下$ch字符的下一个字符是数字还是符号if($index==strlen($exp)-1){$numsStack->push($keepNum);}else{if($operStack->isOper(substr($exp,$index+1,1))){$numsStack->push($keepNum);$keepNum='';}}}$index++;//让index指向下一个字符//判断是否已经扫描完毕if($index==strlen($exp)){break;}//当扫描完毕后就break;}//只要符号栈不空就一直计算while(!$operStack->isEmpty()){$num1=$numsStack->pop();$num2=$numsStack->pop();$oper=$operStack->pop();$res=$operStack->getResult($num1,$num2,$oper);$numsStack->push($res);}//当退出while后,一定有一个数,这个数就是最终结果echo $exp.'='.$numsStack->getTop();//自定义的栈class MyStack{private $top=-1;//默认是-1,表示该栈是空的private $maxSize=5;//$maxSize表示栈的最大容量private $stack=array();//计算的函数public function getResult($num1,$num2,$oper){$res=0;switch($oper){case '+':$res=$num1+$num2;break;case '-':$res=$num2-$num1;break;case '*':$res=$num1*$num2;break;case '/':$res=$num2/$num1;break;}return $res;}//返回栈顶的字符,只是取出不出栈public function getTop(){return $this->stack[$this->top];}//判断优先级的函数public function PRI($ch){if($ch=='*'||$ch=='/'){return 1;}else if($ch=='+'||$ch=='-'){return 0;}}//判断栈是否为空public function isEmpty(){if($this->top==-1){return TRUE;}else{return FALSE;}}//增加一个函数【提示:在我们开发中,根据需要可以灵活增加需要的函数】//判断是不是一个运算符public function isOper($ch){if($ch=='-'||$ch=='+'||$ch=='*'||$ch=='/'){return TRUE;}else{return FALSE;}}//注意类里面的变量一定要用$this->xxx,不然就杯具了//入栈的操作public function push($val){//先判断栈是否已经满了if($this->top==$this->maxSize-1){echo '<br/>栈满,不能添加';return;}$this->top++;$this->stack[$this->top]=$val;}//显示栈的所有数据的方法public function showStack(){if($this->top==-1){echo '<br/>栈空';return;}echo '<br/>当前栈的情况是......';for($i=$this->top;$i>-1;$i--){echo '<br/>stack['.$i.']='.$this->stack[$i];}}//出栈的操作,就是把栈顶取出public function pop(){//判断是否是栈空if($this->top==-1){  echo '<br/>栈空';return;}//把栈顶的值,取出$topVal=$this->stack[$this->top];$this->top--;return $topVal;}}?></html>


原创粉丝点击