要求0 作业地址: https://edu.cnblogs.com/campus/nenu/2016CS/homework/2266
要求1 git仓库地址:https://git.coding.net/Jingr98/f4.git
要求2
一.编程队友及博客地址:张小蕾 https://www.cnblogs.com/zhangxlBlog/p/9926518.html
二.1.解题思路
首先三个功能对应三个表达式生成函数。func1()实现功能1的时候,分奇偶情况利用rand()随机生成操作数和运算符(将4个运算符存入数组中,rand() % 4利用数组下标实现随机)。对于分母为0的特殊情况要进行检验,分母为0时换数(再次生成随机数)直到表达式合法。在func1()的基础上,func2生成的表达式中随机加入小数和小括号,小数由rand()/(double)(RAND_MAX/100)产生。最先遇到的困难就是加括号这里了,开始只考虑了单层括号的情况,因为只有4个运算数,所以单层情况的话对应了6种情况,可以利用rand() % 6随机加括号,但是仔细看了样例发现,还有多层括号嵌套的情况。。。感觉有些复杂,这个地方就去参考学习了一下别人的代码。
然后就是利用压栈的思想来计算四则运算表达式,将输入的中缀表达式用栈转化为后缀表达式,再根据后缀表达式用栈实现运算。先给定两个栈,一个用来存放数字、一个用来存放运算符,计算时把表达式拆分成一个个的数字或运算符或括号,然后从左到右遍历表达式中的每个数字和符号,遇到数字则输出,遇到运算符号,则要比较其与栈顶元素的优先级,若优先级低于栈顶元素,则将栈顶元素依次输出并将该元素入栈;若优先级高于栈顶元素则入栈;若是遇到左括号,入栈,入栈后的左括号优先级低于+ - * / ;若是遇到右括号,则将栈顶元素依次输出,直到遇到左括号,遍历结束后得到后缀表达式。最后利用栈遍历后缀表达式,遍历结束后,最终结果就在栈顶。
2.重点难点
功能一:正确结果的输出格式,尤其是保留小数的位数,不知道怎么将无限小数区分出来。。
功能二:小括号的随机生成,要考虑括号位置的合法性以及左右括号成对出现的问题
功能三:判断表达式是否是重复的(考虑交换律、结合律、分配律变换),感觉这是最困难的
3.编程收获
在这次编程过程中,遇到了很多细节性的问题,有一种每次细想一遍就会发现一个小问题的感觉。在解决问题的过程中,又重新复习了数据结构和算法程序设计的相关知识,用到了栈的存储、中缀表达式与后缀表达式的转化等。最大的感受就是在上网查阅资料的时候,看了挺多代码,了解借鉴了别人的编程思想,get到了很多用C++编程的小技巧。
4.重要代码片段
(1)用point()函数处理输出小数点后面位数的问题。因为无法将无限小数区分开来(考虑到位数很长的有限小数),所以就简单地将用以下方式对结果进行处理,若小数点后面的位数大于3,则按无限小数处理。
/**
*函数名:point()
*函数功能:判断小数点后面的位数是否超过3
*param:double num
*/
int point(double num)
{
int i,f=0;
num *= 1000;
if(num - (int)num > eps)
f = 1;
return f;
}
(2)中缀表达式转后缀表达式,运算符号入栈的过程中利用power()函数判断优先级
/**
*函数名:power()
*函数功能:将'+'、'-'、'*'、'/'、'('、')'赋予优先级
*param:char c
*/
int power(char c)
{
if (c == '-' ||c == '+')
return 1;
else if (c == '*' || c == '/')
return 2;
else if (c == '(' || c == ')')
return 0;
else
return -1;
}
(3)work()函数负责计算四则运算表达式,最终结果存储在栈顶
/**
*函数名:work()
*函数功能:利用双栈将中缀表达式转换成后缀表达式,遍历后缀表达式得到结果
*param:string s
*/
double work(string s )
{
stack<double> sNum; //存储操作数的栈
stack<char> sOp; //存储运算符的栈
int i = 0, flag = 1;
char c;
double x, y;
sOp.push('