上一篇是主要说了表达式的求值,主要目的是使其可以计算带括号的四则混合运算,其实并没有什么实质东西在里面。。。
下面主要说一下表达式的产生;
首先加入两个符号''*和'/',,这个很简单,只需要在下面两处修改一下,然后将产生式计算就可以了
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又出现了问题,,由于牵扯到了库的实现的问题,,这次我不会调试了