用两种方式实现表达式自动计算
五、遇到的问题及解决
这部分我主要遇到了如下两个问题,其内容与解决方法如下所列:
? 1.程序在特定的情况下会计算错误,例如输入表达式3.14*(5+4)-5/2+5%2时,
程序会正确的计算出3.14*(5+4)-5/2的值等于25.76,最后的输出结果却是24.76.
图5 错误的运行结果图
图6 错误的运行结果图
我后来有连续输入了几个算式,发现只要在上面的算式后面加上的加减操作都会得到相反的结果,程序会将加操作变成减操作,将减操作变成加操作。但是输入算式5/2+5%2时,程序又得到了正确的结果。当输入其他的一般算式时,程序会计算出正确的结果,不会出现错误。
我对源代码进行了细致的检查,没有发现比较明显的错误。当使用编译器自带的调试功能调试程序时,通过跟踪压入od栈中的数字,发现前几个计算结果都是正确的,但压入栈中的符号出现了错误,最后的加号变成了减号。我想原因可能出在符号进栈时的优先级判定上。
我复习了关于中缀表达式转换为后缀表达式的符号进栈的规则,发现只有栈外符号优先级大于栈顶优先级时,才允许此符号入栈。在我的源程序中,我写成了只要站外符号优先级不小于栈顶优先级是,就允许此符号入栈。
找到了问题,就要这是知道如何造成的。我通过自己演算,发现了问题:当扫描到了表达式中”5/2”后面的加号时,此时od栈中从栈底开始依次为:28.26-2.5,op栈的栈内只有一个元素为:减号,这个加号与栈中的减号优先级相同,这个加号被压入op栈中。于是,当程序扫描完表达式时,od栈中元素从栈底开始依次为:28.26-2.5-1,op栈中元素从栈底开始依次为:减号-加号。当从op栈中依次出栈时,程序先计算了
- 16 -
用两种方式实现表达式自动计算
5/2+5%2的值,相当于程序计算的表达式为:3.14*(5+4)-(5/2+5%2),于是发生了计算错误的问题。
最后就是解决问题,当把源代码中的错误改过来之后,程序计算结果正确了,问题解决。
? 2.程序运行后,无论输入什么,运算结果总是0
图7 错误的运行结果图
我检查了程序,并未发现明显的逻辑错误。于是,我用printf()语句输出了程序运行后每个压入数值栈od栈中的数值,发现压入od栈中的数字并没有错误,只是最后压入od栈中的数字式0.0。我还用同样的方法输出了每个压入操作符op栈的操作符,发现压入op栈的操作符并没有错误。问题可能是在数据压入od栈中的循环多循环了一次,op栈中多取出了一个空的操作符或者其他原因。
我再次输出了每次对od栈和op栈进行操作时它们栈顶指针的值,发现op栈的指针并不是-1,而是0。问题找到了。
我重新查看了程序,发现在op栈初始化时,我并没有对op栈的栈顶指针进行初始化,程序执行时,将其以默认值赋值成了0,导致最后op栈取出了一个空的操作符,在调用计算函数double re()时,函数没有找到符合要求的case条件,返回了值0,最后0被压入od栈中,导致了错误的结果。
把源代码中的op栈的栈顶指针初始化为0后,问题解决了。
六、心得体会
表达式的计算要用到栈的知识,一开始的时候,不太清楚如何运用结构体构造一个栈,
后来我通过去图书馆借阅书籍和网上查找资料的方法,初步了解了栈的构造和用C语言构造一个栈的方法,还学会了如何灵活的运用指针解决让函数的返回数组指针,通过指针访问栈内元素。在在写第一个程序的过程中,我学会了如何用分步解决问题的方法,先写出如何将中缀表达式转为后缀表达式,确认没有错误后,在计算后缀表达式的值,用逐步解决问题的方法将问题细化,分步解决。程序编写完成后,出现了各种各样的逻辑问题,我学会了如何灵活运用编译器的调试功能,跟踪变量的值,从而确定到底哪个环节出现问题,再深入分析,查看循环的执行过程中是否有遗漏或者重复执行的问题,判断语句是不是有条件矛盾的问题,最后解决问题。在测试第二个程序的时候,我发现程序在输入特定的表达式时,就会出现计算错误的问题,通过细心的调试和分析,我学会了如何分析程序的漏洞并加以改正,从而使程序更加完美。总而言之,通过这次的编写程序,我学会了很多调试程序的方法和思想,收益很大。
- 17 -