上一篇是主要说了表达式的求值,主要目的是使其可以计算带括号的四则混合运算,其实并没有什么实质东西在里面。。。

 

下面主要说一下表达式的产生;

首先加入两个符号''*和'/',,这个很简单,只需要在下面两处修改一下,然后将产生式计算就可以了

static char token[] = {'+','-',' '}====》static char token[] = {'+','-','*','/',' '}

void  DoEnum(int n, int curr, int to[])
{
    if (curr == n)
    {
        GetExpression(to, n);
    }
    else
    {
        for (int i = 0; i<3; ++i)====》  for (int i = 0; i<5; ++i)
        {
            to[curr] = i;
            DoEnum(n, curr+1, to);
        }
    }
}

产生的结果如下:(需要注意的是,因为里面有除法,所以注意用double进行运算,并且注意对除以0的处理)

1+2+3+4+5+6+7+8*9=100   
1+2+3-4+5+6+78+9=100   
1+2+3-4*5-6*7+8*9=100   
1+2+3-45+67+8*9=100   
1+2+3*4-5-6+7+89=100   
1+2+3*4*5/6+78+9=100   
1+2+3*4*56/7-8+9=100   
1+2+34-5+67-8+9=100   
1+2+34*5+6-7-8*9=100   
1+2-3*4+5-6*7+8*9=100   
1+2-3*4-5*6+7+8*9=100   
1+2*3+4+5+67+8+9=100   
1+2*3+4*5-6+7+8*9=100   
1+2*3-4+56/7+89=100   
1+2*3-4-5+6+7+89=100   
1+2*3*4*5/6+7+8*9=100   
1+2*34-56+78+9=100   
1+23-4+5+6+78-9=100   
1+23-4+56+7+8+9=100   
1+23-4+56/7+8*9=100   
1+23-4-5+6+7+8*9=100   
1+23*4+5-6+7-8+9=100   
1+23*4+56/7+8-9=100   
1+23*4-5+6+7+8-9=100   
1+234-56-7-8*9=100   
1+234*5*6/78+9=100   
1+234*5/6-7-89=100   
1-2+3+45+6+7*8-9=100   
1-2+3*4+5+67+8+9=100   
1-2+3*4*5+6*7+8-9=100   
1-2+3*4*5-6+7*8-9=100   
1-2-3+4*5+67+8+9=100   
1-2-3+4*56/7+8*9=100   
1-2-3+45+6*7+8+9=100   
1-2-3+45-6+7*8+9=100   
1-2-3+45-6-7+8*9=100   
1-2-34+56+7+8*9=100   
1-2*3+4+5-6*7+8*9=100   
1-2*3+4-5*6+7+8*9=100   
1-2*3-4*5+6+7+8*9=100   
1-23+4*5+6+7+89=100   
1-23-4+5*6+7+89=100   
1-23-4-5+6*7+89=100   
1*2+3+4*5+6+78-9=100   
1*2+3+45+67-8-9=100   
1*2+3-4+5*6+78-9=100   
1*2+3*4+5-6+78+9=100   
1*2+34+5+6*7+8+9=100   
1*2+34+5-6+7*8+9=100   
1*2+34+5-6-7+8*9=100   
1*2+34+56+7-8+9=100   
1*2+34-56/7-8*9=100   
1*2-3+4+56/7+89=100   
1*2-3+4-5+6+7+89=100   
1*2-3+4*5-6+78+9=100   
1*2*3+4+5+6+7+8*9=100   
1*2*3-4+5+6+78+9=100   
1*2*3-4*5-6*7+8*9=100   
1*2*3-45+67+8*9=100   
1*2*3*4+5+6+7*8+9=100   
1*2*3*4+5+6-7+8*9=100   
1*2*3*4-5-6+78+9=100   
1*2*34+56-7-8-9=100   
1*2/3+4*5/6+7+89=100   
1*23+4+5+67-8+9=100   
1*23+4+56/7*8+9=100   
1*23-4+5-6-7+89=100   
1*23-4-56/7-89=100   
1*23*4-56/7/8-9=100   
1*234+5-67-8*9=100   
1/2*3/4*56+7+8*9=100   
1/2*34-5+6-7+89=100   
1/2/3*456+7+8+9=100   
12+3+4+5-6-7+89=100   
12+3+4-56/7-89=100   
12+3-4+5+67+8+9=100   
12+3*4+5+6+7*8+9=100   
12+3*4+5+6-7+8*9=100   
12+3*4-5-6+78+9=100   
12+3*45+6*7-89=100   
12+34+5*6+7+8+9=100   
12+34-5+6*7+8+9=100   
12+34-5-6+7*8+9=100   
12+34-5-6-7+8*9=100   
12-3+4*5+6+7*8+9=100   
12-3+4*5+6-7+8*9=100   
12-3-4+5-6+7+89=100   
12-3-4+5*6+7*8+9=100   
12-3-4+5*6-7+8*9=100   
12*3-4+5-6+78-9=100   
12*3-4-5-6+7+8*9=100   
12*3-4*5-67-8-9=100   
12/3+4*5-6-7+89=100   
12/3+4*5*6-7-8-9=100   
12/3+4*5*6*7/8-9=100   
12/3/4+5*6+78-9=100   
123+4-5+67-89=100   
123+4*5-6*7-8+9=100   
123+45-67+8-9=100   
123-4-5-6-7+8-9=100   
123-45-67+89=100  

下一步需要做的就是把括号加入进来,

首先我们应该意识到的就是,应该加入语法分析了,因为产生式可能出现“)(”这样的情况,所以必须在产生式计算前进行语法分析,把不符合的产生式淘汰。。

其次,很直观的我们还认为是和加入乘除一样,只需要多添两个符号就可以了,于是我就试验了一下,,结果发现结果里居然没有带括号的。dubeg一下,原来产生式变成了“1+2+3+4(5-6+7+8+9”,这样所有带括号的产生式都被淘汰了。。。

于是我了解到原来括号和一般的符号是不同的,它一般至少有两个符号同时存在,如“3+(4-5)”,而且还可能出现嵌套,如“3+((4+5)*6)”,

 

这时,我有了一种思路就是  ,先产生式子"1%c2%c3%c4%c5%c6%c7%c8%c9"的所有情况,这也需要一个递归,简单计算一下,一共八个位置,每个位置的情况“"%c","%c%c"","%c%c%c",...“最多也就七层嵌套,那么需要7^8次循环,,我试验时没有考虑嵌套,两个小时后还没计算完,然后我就关了。。

然而这个思路还带了一个问题就是sprintf语句不好写,因为它的第三参数,

  sprintf(buff, "1%c2%c3%c4%c5%c6%c7%c8%c9",
        token[a[0]], token[a[1]], token[a[2]], token[a[3]],
        token[a[4]], token[a[5]],token[a[6]], token[a[7]]);

并不是它的个数不能确定,第三参数的个数我在产生式子的同时也计算出来了,弄了个map<string,int>存储,现在就是token[a[i]]这个不好写,因为它是动态的,不能够根据i来动态的产生sprintf语句。在我那个没有嵌套的试验中,我用的switch语句,也就几种case,每一个case一个sprintf语句。。如果有嵌套的话,就不好弄了,因为case太多了。。

 

 

于是乎我换个了思路,把"+("看成整体插进去,,

  string token[] = {"+","-","*","/","+(" ,"-(","*(","/(",")+",")-",")*",")/"," "};//没有考虑嵌套

这样的话立即就简单了,不仅减少了语法分析的次数,同时也解决了sprintf的问题。。

 string token[] = {"+","-","*","/","+(" ,"-(","*(","/(",")+",")-",")*",")/"," "};   
  
  oss.str(
"");   
 oss
<<1<<token[a[0]]<<2<<token[a[1]]<<3<<token[a[2]]<<4<<token[a[3]]   
  
<<5<<token[a[4]]<<6<<token[a[5]]<<7<<token[a[6]]<<8<<token[a[7]]<<9//9577次时出现异样   
  
void  DoEnum(int n, int curr, int to[])   
{   
    
if (curr == n)   
    
{   
        GetExpression(to, n);   
    }
   
    
else  
    
{   
        
for (int i = 0; i<13++i)   
        
{   
            to[curr] 
= i;   
            DoEnum(n, curr
+1, to);   
        }
   
    }
   
}
  

如果想要嵌套的话,在加几种情况就行了。。

这样看起来就要可以了,可是又出现了一个问题,在9577次时oss又出现了问题,,由于牵扯到了库的实现的问题,,这次我不会调试了