本次作业的题目:
在四则运算2的基础上,再添加一些条件,总共要求满足如下条件:
1.题目避免重复。
2.可制定。(数量/打印方式)
3.可以控制下列参数:
- 是否有乘除法
- 是否有括号(最多可支持10个数参与计算)
- 数值范围
- 加减有无负数
- 乘除有无余数
(新要求)
4.学生写的程序必须能判定用户的输入答案是否正确
5.程序必须能处理混合四则运算
PS:连续的减法和除法,应该遵循做结合的规定;连续除法要打括号。
设计思想:
1.因为这次是结对开发,两个人结对,并且再上一次的程序基础上进行拓展,所以比较了一下各自的程序,选出较优秀的那一个。
2.由于要完成的功能非常多,可以划分多个模块实现,便于多个功能组合。
3.第一个模块就是出现连除的情况,我们程序是随机出现括号的,如果出现连除的情况,必须在后方添加括号。
4.括号的实现,利用整型转化成字符串型来进行解决,括号随机出现左边或者右边,保存在数组之内。
5.实现真分数以及真分数的运算,运算方式直接利用分数的加减乘除运算规则来实现。
6.结果的验证,将四则运算算式转化成字符串,利用压栈入栈的数据结构计算四则运算表达式,正确的结果与输出入的结果进行比较,得出答案是否正确。
代码:
//随机生成四则运算表达式 杨超群 杨涛 2016.3.12#include#include #include #include #include #include #include #include #include #include #define MAX 100#define False 0#define True 1using namespace std;typedef string SelemType;using namespace std;string str1[4]={ "+","-","*","/"}; //运算符数组,存储+ - * /int n,m;int num[6]; //随机生成的操作数char str2[25]; //整数转化为的字符数组char str3[25]; //整数转化为的字符数组string str4[100];int OperatorNum[1000]; //运算符数组,每生成一个运算符存进数组typedef struct{ SelemType *base; SelemType *top; int stacksize;}Sqstack;void InitStack(Sqstack &s) //栈的初始化{ s.base=new SelemType[MAX]; if(!s.base)exit(1); s.top=s.base; s.stacksize =MAX;}void Push(Sqstack &s,SelemType e) //压入{ if(s.top-s.base==s.stacksize) exit(1); *s.top++=e;}void Pop(Sqstack &s,SelemType &e) //弹出{ if(s.top==s.base) exit(1); e=*--s.top;}SelemType GetTop(Sqstack &s) //取顶{ if(s.top==s.base) exit(1); return *(s.top-1);}int In(SelemType ch) //判断是否为运算符{ if(ch=="+"||ch=="-"||ch=="*"||ch=="/"||ch=="("||ch==")"||ch=="#") return True; else return False;}SelemType Operate(SelemType a1,SelemType theta,SelemType b1) //计算{ stringstream ss; SelemType c1; double m1,m2; double m3,m4; m1=atof(a1.c_str()); m2=atof(b1.c_str()); if(theta=="+") m3=m1+m2; else if(theta=="-") m3=m1-m2; else if(theta=="*") m3=m1*m2; else if(theta=="/") m3=m1/m2; m4=double((int)(m3*100))/100.0; ss< >c1; return c1;}char Precede(string theta1,string theta2) //运算符的计算顺序判断{ char chx; if(theta1=="+") { if(theta2=="*"||theta2=="/"||theta2=="(") chx = '<'; else chx = '>'; } else if(theta1=="-") { if(theta2=="*"||theta2=="/"||theta2=="(") chx = '<'; else chx = '>'; } else if(theta1=="*") { if(theta2=="(") chx = '<'; else chx = '>'; } else if(theta1=="/") { if(theta2=="(") chx = '<'; else chx = '>'; } else if(theta1=="(") { if(theta2==")") chx = '='; else if(theta2=="#") chx='$'; else chx = '<'; } else if(theta1==")") { if(theta2=="(") chx = '$'; else chx = '>'; } else if(theta1=="#") { if(theta2=="#") chx = '='; else if(theta2==")") chx='$'; else chx = '<'; } return chx;}string TiQuString(string str,int &i){ string ch; char *q; string p; p=str; q=&p[i]; ch=ch+*q; if((*q>='0')&&(*q<='9')) { i++; int j=1; while((*(q+j)>='0')&&(*(q+j)<='9')) { ch=ch+*(q+j); j++; } i=i+j-1; } else { ch=*q; i++; } return ch;}string OPeration(string str){ string str1; str1=str+"#"; int i=0; string ch; ch=TiQuString(str1,i); SelemType theta,x1,a1,b1; Sqstack OPND,OPTR; InitStack(OPTR); InitStack(OPND); Push(OPTR,"#"); while(ch!="#"||GetTop(OPTR)!="#") { int f; f=In(ch); if(f!=True) { Push(OPND,ch); ch=TiQuString(str1,i); } else { switch(Precede(GetTop(OPTR),ch)) { case '<': { Push(OPTR,ch); ch=TiQuString(str1,i); break; } case '>': { Pop(OPTR,theta); Pop(OPND,b1);Pop(OPND,a1); Push(OPND,Operate(a1,theta,b1)); break; } case '=': { Pop(OPTR,x1); ch=TiQuString(str1,i); break; } case '$': { cout<<"该表达式有错"; break; } default:break; } } } return GetTop(OPND);} void Input(int n,int p,int min,int max,int &j,int &q){ int num1,num2,num3,num4,num5; //随机数 int c=0; //指向第一个运算符数组的下标 int s=0; //括号的个数 string str; ofstream outfile; outfile.open("a.txt",ios::app); if(!outfile) { cerr<<"OPEN ERROR!"< >result1; if(result1==result2) { cout<<" 计算正确"; j++; cout<<"计算错误,答案是"< num[j]) { int temp=0; temp=num[i]; num[i]=num[j]; num[j]=temp; } } } }void sort1(int min,int max) //生成两个随机数,并排序{ num[4]=rand()%(max-min+1)+min; num[5]=rand()%(max-min+1)+min; for(int i=4;i<6;i++){ for(int j=4;j num[j]) { int temp=0; temp=num[i]; num[i]=num[j]; num[j]=temp; } } } }void Simplification(int &m,int &n) //真分数化简{ int x,y,i,p; //公约数p if(m>=n) { x=n; y=m; } if(m 0;i--) { if(x%i==0&&y%i==0) { p=i; break; } } m=m/p; n=n/p;}void Input2(int n,int p,int min,int max,int &j,int &q){ int num3,num4,s=0; string str,strr2,strr3,str5,str6,str7,str8,str9; stringstream ss1,ss2,ss3,ss4,ss5,ss6,ss7,ss8; ofstream outfile; outfile.open("a.txt",ios::app); if(!outfile) { cerr<<"OPEN ERROR!"< >strr2; ss2< >strr3; ss3< >str5; ss4< >str6; if((str5!=strr3)&&(str6!=strr2)) //避免生成分子分母相等的表达式 str="("+str5+"/"+strr3+")"+str1[num3]+"("+str6+"/"+strr2+")"; else if(str5==strr3) str=str5+str1[num3]+"("+str6+"/"+strr2+")"; else if(str6==strr2) str="("+str5+"/"+strr3+")"+str1[num3]+str6; n=n-4; while(n!=0) //当n不等于0时,循环生成str,即表达式+符号+表达式的形式 { num4=rand()%2; if(num4==0) //上一个str放在符号的左边 { sort1(min,max); Simplification(num[4],num[5]); num3=rand()%4; ss5< >str7; ss6< >str8; if(str7!=str8) //避免生成分子分母相等的表达式 str9="("+str8+"/"+str7+")"; else str9=str8; str=str+str1[num3]+str9; } else //上一个str放在符号的右边 { sort1(min,max); Simplification(num[4],num[5]); num3=rand()%4; ss7< >str7; ss8< >str8; if(str7!=str8) //避免生成分子分母相等的表达式 str9="("+str8+"/"+str7+")"; else str9=str8; str=str9+str1[num3]+str; } n=n-2; } string result1,result2; str4[p]=str; //把str存入字符串数组str4中 for(int i=0;i >result1; if(result1==result2) { cout<<" 计算正确"; j++; } else { cout<<"计算错误,答案是"<
>x; switch(x) { case 1: { cout<<"取值范围最小值(大于等于1):"; cin>>min; cout<<"取值范围最大值:"; cin>>max; cout<<"有(无)括号运算(注释:真分数必须加括号,以防形成6/3/2的形式)---有(1),无(0):"; cin>>y; cout<<"题目数量:"; cin>>n; cout<<" 测试开始 "< >min; cout<<"取值分子分母范围最大值(大于等于1):"; cin>>max; cout<<"题目数量:"; cin>>n; cout<<" 测试开始 "<
实验总结:
第一次体验了结对开发编程,其中的好处不言而喻,锻炼了团队沟通能力,团结协作解决问题的能力。但是有时候难免会产生分歧,这个时候就要仔细认真沟通,想出解决办法,而不是互相抱怨,从中获益了很多,这次程序难度感觉还是很大,重新回去学习了相关的知识,例如数据结构与算法。还是利用分模块的编程理念,一步一步从最简单入手,完成小功能,再慢慢整合,一步一步攻克难关。最后完成了任务,很有成就感,团队荣誉感。
项目计划总结:
日期&&任务 | 听课 | 编写程序 | 阅读相关书籍 | 网上查找资料 | 日总计 |
周一 | 100 | 25 | 25 | 15 | 165 |
周二 | 30 | 35 | 25 | 90 | |
周三 | 60 | 15 | 35 | 110 | |
周四 | 100 | 30 | 30 | 25 | 185 |
周五 | 180 | 15 | 195 | ||
周六 | 60 | 15 | 75 | ||
周日 | 15 | 15 | |||
周总计 | 200 | 325 | 180 | 130 | 835 |
时间记录日志
日期 | 开始时间 | 结束时间 | 中断时间 | 净时间 | 活动 | 备注 |
3/14 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程上课 |
17:10 | 17:20 | 10 | 阅读书籍 | 《构建之法》《梦断代码》 | ||
21:00 | 21:25 | 20 | 网上查找资料 | |||
3/15 | 14:00 | 15:00 | 10 | 110 | 编程 | 编写老师布置的作业 |
16:00 | 17:00 | 10 | 110 | 看书 | 《构建之法》《梦断代码》 | |
3/16 | 21:00 | 21:30 | 30 | 编程 | 编写老师布置的作业 | |
3/17 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程上课 |
3/18 | 16:00 | 18:00 | 120 | 编程 | 编写老师布置的作业 | |
3/19 | 9:00 | 9:30 | 30 | 看书 | 《构建之法》《梦断代码》 | |
3/20 | 9:00 | 9:30 | 30 | 看书 | 《构建之法》《梦断代码》 |
缺陷记录日志:
日期 | 编号 | 类型 | 引入阶段 | 排除阶段 | 修复时间 | 修复缺陷 |
3月15日 | 1 | 编码 | 编码 | 0.2min | ||
缺少头文件 | ||||||
2 | 编码 | 运行 | 3min | |||
重复使用变量i,导致无限运行 | ||||||
3月18日 | 3 | 编码 | 编译 | 1min | ||
if条件中用了“=”运算符 | ||||||
4 | 编码 | 编译 | 1min | |||
switch的case中缺少了break | ||||||
5 | 编码 | 编译 | 0.2min | |||
for的结尾再次使用i++,导致i加了两次 |
小组照片:
小组成员:杨超群