本周我开始了我的第一个个人软件工程项目——自动生成算式。在做这个看似没事什么难度的项目的过程中,我的收获还是有很多的。
我这个人解决问题的一般思路基本上都是由简到繁,循序渐进。所以我首先并没有考虑如何随机生成算式,而是怎样让程序从txt文档中读入算式,然后再进行计算。首先我来搞定10以内的四则运算。具体方法是将写在txt文档中的算式以string的格式读入到程序中,然后按照在数据结构课中学到的方法把这个中缀表达式转换成后缀表达式,然后计算这个后缀表达式。Ok,接下来我来做10以上的数的四则运算,这就涉及到string和int的相互转换问题,让我想到了以前接触过的stringstream类,这个东西虽然好像效率不是特高,但是对于我们这种工程来说应该够用了。在搞定了这些之后,我接着思考怎样既能进行整数运算又能进行分数运算。我想最好的方法应该就是建立一个统一的标准才行。所以我写了一个分数的struct,包括int分子和int分母,还写了分数四则运算函数。整个计算过程均为分数运算,即把所有整数都当成分母为1的分数。最后在对得到的分数结果进行化简即可。
做完了这些,完成了这个工程的基本要求,接下里我来思考怎样自动生成算式。由于要生成各种类型的表达式,而各式各样的表达式都可以用二叉树的形式来描述,所以我想到用满二叉树来生成算数表达式。有了大致思路,接下来我开始考虑细节的问题。首先要确定的是这棵树的内部节点是运算符,叶子节点就是操作数。接下来怎样让表达式的长度随机呢。我想从根开始,每个节点以一定的概率(如1/2)生成他的子节点即可但又不能无限生长下去,所以要控制整棵树的最大深度。然后就是操作数和运算符也要随机生成,这个好说。那么怎样计算表达式的值呢?从叶子节点开始自底向上计算即可,这个写个递归函数比较好实现。恢复整个表达式?依然是让每个节点保存一个string记录这个节点及他的两棵子树形成的表达式,再自底向上生成整个表达式即可。还需要注意的一个点就是生成表达式的时候是否需要加括号。这个需要根据子节点运算符的优先级和父节点运算符的优先级来确定。
有了大致思路,我就开始实现了,整个过程比较悲催的一点是之前写好的算法基本上没什么用了。主要的代码全部要重新写。这也是我由简到繁的方法的一个弊端所在——没有从整体考虑问题,之前做的工作在之后有可能完全用不到。
好了,我目前的进展大概就是这样,不知道我的方法是不是有点low。