Naeioi

量子の風
随笔 - 8, 文章 - 0, 评论 - 0, 引用 - 0
数据加载中……

栈-表达式求值

   所谓表达式求值就是用计算机计算加减乘除式子,说的装逼一点,就是计算中缀表达式的值。
   5 + ((1 + 2) * 4) − 3
   我们把这个式子添上括号,保持计算顺序不变。
   (5+((1+2)*4))-3)
   运算符夹在数字中间,“中缀”之名由此得来。
   人脑可以很快判断计算先后顺序,其实这个过程不是那么显然。因为*/+-有优先级,括号的加入又会打破这个规则。我们可以找出一个式子中最后进行的一步运算,对它的两边分别计算,在根据运算符进行合并。
   (5+((1+2)*4))-3)
  
下面挂的代码是递归实现的。不要骂我标题党,不久会更新真正的栈实现代码,这需要时间,时间~再说递归才符合思维习惯,也更便于记忆~!//表达式求值(递归实现) 
/*Author:naeioi
Prog:C++ 
Time:11.10.22
*/
#include <cstdio>
#include <cstring>
using namespace std;

const int maxl=100;
char s[maxl];

#define isnum(a) (a>='0'&&a<='9')
#define isop(a) (a=='+'||a=='-'||a=='*'||a=='/')

int match(int i)
{
    int count=1;
    while(count!=0){
          i++;
          if(s[i]=='(') ++count;
          if(s[i]==')') --count;
    }
    return i;
}

int ston(int p)//下标从p开始
{
    int ans=0,positive=1;//符号 
    if(s[p]=='-'){++p; positive=-1;}
    while(isnum(s[p])){
          ans*=10;
          ans+=s[p++]-'0';
    }
    return ans*positive;;
}

int div(int l,int r)//求l~r(下标)表示的式子的值 
{
    while(s[l]=='('&&match(l)==r){++l; --r;}//去除多余括号。不能写成s[l]=='('&&s[r]=')',形如(1+2)*(3+4)的式子会错误 
    if(l>r) return 0;
    
    int pos,prior=3;//优先级,2==*/,1==+-
    for(int i=l;i<=r;i++){//找优先级最小的运算符 
        if(s[i]=='(')
           if((i=match(i)+1)>r)
              break;
        if(s[i]=='*'||s[i]=='/')
        {  if(prior>=2){pos=i; prior=2;}}
        else if(s[i]=='+'||s[i]=='-')
                if(prior>=1&&i!=l&&!isop(s[i-1])){pos=i; prior=1;}//-接在运算符后时看成符号。否则看成减号 
    }
    
    if(prior==3)//是一个数
       return ston(l); 
    
    int a=div(l,pos-1),b=div(pos+1,r),ans;
    switch(s[pos])
    {
                  case '+':
                       ans=a+b;
                       break;
                  case '-':
                       ans=a-b;
                       break;
                  case '*':
                       ans=a*b;
                       break;
                  case '/':
                       ans=a/b;
                       break;
    }
    return ans;
}

int main()
{
    freopen("eval.in","r",stdin);
    freopen("eval.out","w",stdout);
    
    scanf("%s",s);
    
    printf("%d",div(0,strlen(s)-1));
    
    fclose(stdin);
    fclose(stdout);
    return 0;
}

posted on 2011-10-22 23:12 Naeioi Zhu 阅读(450) 评论(0)  编辑 收藏 引用 所属分类: 标准代码库


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理