软件工程随堂小作业——随机四则运算Ⅱ(C++)
一、设计思路
设计思路已给出,此处不再赘述。
二、源代码
(1)四则运算2.cpp(源文件)
1 // 四则运算2.cpp : Defines the entry point for the console application. 2 // 袁佩佩 信1201-1班 20122785 2015/3/15 3 4 #include "stdafx.h" 5 #include "iostream.h" 6 #include "stdlib.h" 7 #include "time.h" 8 #include "Caculation.h" 9 #include "iomanip.h" 10 11 //******重新生成算术题****** 12 void ReBuild(Caculation &Q) 13 { 14 if(para[4]==1) 15 Q.sign=rand()%4; 16 else 17 Q.sign=rand()%2; 18 Q.num1=rand()%(para[6]-para[5]+1)+para[5]; 19 Q.num2=rand()%(para[6]-para[5]+1)+para[5]; 20 } 21 //*****输出函数****** 22 void Display(LinkC C,Caculation &Q) 23 { 24 int temp,count=0; //count记录重新生成题目的次数 25 for(int i=1;i<=para[1];i++) 26 { 27 cout<<"("<<i<<")"; 28 if(para[4]==1) 29 Q.sign=rand()%4; //有乘除法 30 else 31 Q.sign=rand()%2; //没有乘除法 32 Q.num1=rand()%(para[6]-para[5]+1)+para[5]; //随机的(下限~上限)以内的整数 33 Q.num2=rand()%(para[6]-para[5]+1)+para[5]; 34 RB: ReBuild(Q); //检查是否有出过的题目 35 if(count>((para[6]-para[5]+1)*(para[6]-para[5]+1)*100)) 36 { 37 cout<<endl<<"该难度的题目已出完,请更改出题设置!"<<endl; 38 break; 39 } 40 switch(Q.sign) 41 { 42 case 0: 43 if(ExistQues(C,Q)) 44 { 45 count++; 46 goto RB; 47 } 48 cout<<Q.num1<<"+"<<Q.num2<<"="<<setw(5); 49 break; 50 case 1: 51 if((para[7]==0)&&(Q.num1<Q.num2)) 52 { //若为负数,则交换 53 temp=Q.num1; 54 Q.num1=Q.num2; 55 Q.num2=temp; 56 } 57 if(ExistQues(C,Q)) 58 { 59 count++; 60 goto RB; 61 } 62 cout<<Q.num1<<"-"<<Q.num2<<"="<<setw(5);break; 63 case 2: 64 if(ExistQues(C,Q)) 65 { 66 count++; 67 goto RB; 68 } 69 cout<<Q.num1<<"*"<<Q.num2<<"="<<setw(5);break; 70 case 3: 71 while(Q.num2==0) 72 Q.num2=rand()%(para[6]-para[5]+1)+para[5]; 73 if(!para[8]) 74 { 75 while((Q.num1%Q.num2)!=0||Q.num2==0) 76 { //重新生成 77 Q.num1=rand()%(para[6]-para[5]+1)+para[5]; 78 Q.num2=rand()%(para[6]-para[5]+1)+para[5]; 79 } 80 } 81 if(ExistQues(C,Q)) 82 { 83 count++; 84 goto RB; 85 } 86 cout<<Q.num1<<"/"<<Q.num2<<"="<<setw(5);break; 87 } 88 InsertQues(C,Q); 89 if(i%para[2]==0) //一行打印完规定列数,换行 90 for(int j=0;j<=para[3];j++) 91 cout<<endl; 92 } 93 cout<<endl<<endl; 94 } 95 //*****判断难度***** 96 void YesOrNo(int para) 97 { 98 if(para) 99 cout<<"是"; 100 else 101 cout<<"否"; 102 } 103 //*****查看设置***** 104 void ShowSetting() 105 { 106 system("cls"); 107 cout<<"\t/*************四则运算出题系统*************/"<<endl; 108 cout<<"\t题目数量:"<<para[1]<<"个\t\t打印列数:"<<para[2]<<"列"<<endl; 109 cout<<"\t每行间隔:"<<para[3]<<"行\t\t是否有乘除法:";YesOrNo(para[4]);cout<<endl; 110 cout<<"\t数值范围下限:"<<para[5]<<"\t\t数值范围上限:"<<para[6]<<endl; 111 cout<<"\t是否有负数:";YesOrNo(para[7]);cout<<"\t\t是否有余数:";YesOrNo(para[8]);cout<<endl; 112 cout<<"\t/******************************************/"<<endl; 113 } 114 //*****设置打印方式***** 115 void SetPrint() 116 { 117 system("cls"); 118 char move1; 119 cout<<"\t/*************设置打印方式*************/"<<endl; 120 cout<<"\t 0.设置打印列数("<<para[2]<<"列)"<<endl; 121 cout<<"\t 1.设置每行间隔("<<para[3]<<"行)"<<endl; 122 cout<<"\t 2.返回主菜单"<<endl; 123 cout<<"\t/**************************************/"<<endl; 124 cout<<"请选择后续操作(0~2):"; 125 cin>>move1; 126 while(move1<'0'||move1>'2') 127 { 128 cout<<"错误!请正确输入操作序号(0~2):"; 129 cin>>move1; 130 } 131 switch(move1) 132 { 133 case '0': 134 reset2: cout<<"新的打印列数(建议7列以内):"; 135 cin>>para[2]; 136 if(para[2]<0) 137 { 138 cout<<"出错!请重新输入!"<<endl; 139 goto reset2; 140 } 141 break; 142 case '1': 143 reset3: cout<<"新的间隔行数:"; 144 cin>>para[3]; 145 if(para[3]<0) 146 { 147 cout<<"出错!请重新输入!"<<endl; 148 goto reset3; 149 } 150 break; 151 case '2':break; 152 } 153 } 154 //*****判断输入正确***** 155 void Reset(int i) 156 { 157 do 158 { 159 cout<<"请重新设置(是1/否0):"; 160 cin>>para[i]; //此处输入字符出错,但没解决 161 }while(para[i]!=0&¶[i]!=1); 162 } 163 //*****设置题目难度***** 164 void SetLevel() 165 { 166 system("cls"); 167 char move2; 168 cout<<"\t/*************设置题目难度*************/"<<endl; 169 cout<<"\t 0.是否有乘除法(";YesOrNo(para[4]);cout<<")"<<endl; 170 cout<<"\t 1.数值范围("<<para[5]<<"~"<<para[6]<<")"<<endl; 171 cout<<"\t 2.是否有负数(";YesOrNo(para[7]);cout<<")"<<endl; 172 cout<<"\t 3.是否有余数(";YesOrNo(para[8]);cout<<")"<<endl; 173 cout<<"\t 4.返回主菜单"<<endl; 174 cout<<"\t/**************************************/"<<endl; 175 cout<<"请选择后续操作(0~4):"; 176 cin>>move2; 177 while(move2<'0'||move2>'4') 178 { 179 cout<<"错误!请正确输入操作序号(0~4):"; 180 cin>>move2; 181 } 182 switch(move2) 183 { 184 case '0':Reset(4);break; 185 case '1': //此处若输入字符,则出错 186 reset1: cout<<"新的数值下限:"; //但没找到解决方法 187 cin>>para[5]; 188 cout<<"新的数值上限:"; 189 cin>>para[6]; 190 if(para[5]>=para[6]) 191 { 192 cout<<"出错!请重新输入数值范围!"<<endl; 193 goto reset1; 194 } 195 break; 196 case '2':Reset(7);break; 197 case '3':Reset(8);break; 198 case '4':break; 199 } 200 } 201 //****主页面***** 202 void MainMenu(LinkC &C,Caculation &Q) 203 { 204 char move,save; 205 cout<<"\t/*************四则运算出题系统*************/"<<endl; 206 cout<<"\t 0.开始出题"<<endl; 207 cout<<"\t 1.设置出题数量"<<endl; 208 cout<<"\t 2.设置打印方式"<<endl; 209 cout<<"\t 3.设置题目难度"<<endl; 210 cout<<"\t 4.查看当前设置"<<endl; 211 cout<<"\t 5.退出系统"<<endl; 212 cout<<"\t/******************************************/"<<endl; 213 cout<<"请选择后续操作(0~5):"; 214 cin>>move; 215 while(move<'0'||move>'5') 216 { 217 cout<<"错误!请正确输入操作序号(0~5):"; 218 cin>>move; 219 } 220 switch(move) 221 { 222 case '0':Display(C,Q);break; 223 case '1': 224 reset4: cout<<"请设置出题数量(建议100道以内):"; 225 cin>>para[1]; 226 if(para[1]<=0) 227 { 228 cout<<"出错!请重新输入!"<<endl; 229 goto reset4; 230 } 231 break; 232 case '2':SetPrint();break; 233 case '3':SetLevel();break; 234 case '4':ShowSetting();break; 235 case '5': 236 cout<<"是否保存出题记录(是1/否0):"; 237 cin>>save; 238 while(save!='1'&&save!='0') 239 { 240 cout<<"出错!请正确输入(是1/否0):"; 241 cin>>save; 242 } 243 if(save=='1') 244 WriteQues(C); 245 cout<<"感谢您的使用,再见!"<<endl; 246 para[0]=0;break; 247 } 248 } 249 250 int main(int argc, char* argv[]) 251 { 252 srand((unsigned)time(NULL)); //srand()函数产生一个以当前时间开始的随机种子 253 LinkC Cacu; 254 Caculation ques; 255 InitList(Cacu); 256 ReadQues(Cacu); 257 while(para[0]) 258 { 259 system("cls"); 260 MainMenu(Cacu,ques); 261 system("pause"); 262 } 263 return 0; 264 }
(2)Caculation.h(数据结构头文件)
1 #include "iostream.h" 2 #include "fstream.h" 3 4 //0退出、1出题数量、2打印列数、3每行间隔、4乘除、5数值范围下限、6数值范围上限、7负数、8余数、9出过的题目数 5 int para[10]={1,30,3,0,1,0,99,1,0,0}; //默认参数 6 7 //*****四则算术题的数据结构***** 8 typedef struct 9 { 10 int num1; 11 int num2; 12 int sign; 13 }Caculation; 14 typedef struct CNode //结点 15 { 16 Caculation ques; 17 struct CNode * next; 18 }CNode,*LinkC; 19 //******题目初始化****** 20 void InitList(LinkC &C) 21 { 22 C=new CNode; 23 C->next=NULL; 24 } 25 //******添加题目信息****** 26 void InsertQues(LinkC &C,Caculation Q) 27 { //尾插入 28 LinkC tail,temp; 29 tail=C; 30 while(tail&&tail->next!=NULL) 31 tail=tail->next; 32 temp=new CNode; 33 temp->ques=Q; 34 temp->next=NULL; 35 tail->next=temp; 36 tail=temp; 37 para[9]++; 38 } 39 //******判断题目存在****** 40 int ExistQues(LinkC C,Caculation Q) 41 { 42 LinkC temp; 43 temp=C->next; 44 while(temp) 45 { 46 if((temp->ques.num1==Q.num1)&&(temp->ques.num2==Q.num2)&&(temp->ques.sign==Q.sign)) 47 return 1; //当两个数字和算符与文件中的一样,则存在 48 else 49 temp=temp->next; 50 } 51 return 0; 52 } 53 //******读取出过的问题****** 54 void ReadQues(LinkC &C) 55 { 56 LinkC temp; 57 ifstream infile("question.txt"); 58 for(int i=0;i<10;i++) //读取参数表 59 infile>>para[i]; 60 for(i=0;i<para[9];i++) //读取出过的题目 61 { 62 temp=new CNode; 63 infile>>temp->ques.num1; 64 infile>>temp->ques.num2; 65 infile>>temp->ques.sign; 66 temp->next=NULL; 67 } 68 } 69 //******写入文件****** 70 void WriteQues(LinkC C) 71 { 72 LinkC temp; 73 ofstream outfile("question.txt"); 74 if(!outfile) 75 { 76 cout<<"文件存储失败!"<<endl; 77 exit(0); 78 } 79 for(int i=0;i<10;i++) 80 outfile<<para[i]<<" "; 81 for(temp=C->next;temp;temp=temp->next) 82 { 83 outfile<<temp->ques.num1<<" "; 84 outfile<<temp->ques.num2<<" "; 85 outfile<<temp->ques.sign<<" "; 86 } 87 }
该程序不是特别完美,若有bug和改进方案,欢迎交流。
三、截图
第一次使用时,程序默认10以内四则运算10道题,有负数余数,分三列打印,每行间隔一行。见下图。
对参数进行一些修改。见下图。
对打印方式进行修改。见下图。
对题目的一些设置
退出系统,可选择保存出过的题目和参数设置。
后来经过我的代码优化,当某种类型的题目全部都出过以后,会提示。
首先当前设置如下。
连续出题多次发现
四、PSP0级 记录表
项目计划总结:
周活动总结表
姓名:袁佩佩 日期:15/3/14
日期 任务 |
听课 |
编写程序 |
阅读课本 |
准备考试 |
|
|
日总计 |
周日 |
|
|
|
|
|
|
|
周一 |
|
|
|
|
|
|
|
周二 |
300 |
|
20 |
|
|
|
320 |
周三 |
100 |
70 |
30 |
|
|
|
200 |
周四 |
200 |
115 |
5 |
|
|
|
320 |
周五 |
200 |
40 |
30 |
|
|
|
270 |
周六 |
|
43 |
10 |
|
|
|
53 |
周总结 |
800 |
268 |
95 |
|
|
|
1163 |
阶段时间和效率 周数(上一次周活动表的周数+1):1
不包括上一周在内的累计时间
总计 |
|
|
|
|
|
|
|
平均 |
|
|
|
|
|
|
|
最大 |
|
|
|
|
|
|
|
最小 |
|
|
|
|
|
|
|
以前各周的累计时间
总计 |
800 |
268 |
95 |
|
|
|
1163 |
平均 |
800 |
268 |
95 |
|
|
|
1163 |
最大 |
800 |
268 |
95 |
|
|
|
1163 |
最小 |
800 |
268 |
95 |
|
|
|
1163 |
时间记录表:
学生 袁佩佩 日期 15/3/14
教师 王建民 课程 PSP
日期 |
开始时间 |
结束时间 |
中断时间 |
净时间 |
活动 |
备注 |
15/3/11 |
8:00 |
9:50 |
10 |
100 |
计算机网络上课 |
课间10分钟休息 |
|
16:20 |
16:50 |
|
30 |
阅读《梦断代码》 |
|
|
17: 44 |
18:37 |
20 |
33 |
编写四则运算程序 |
填写PSP记录表 |
|
23:00 |
23:37 |
|
37 |
编写四则运算程序 |
|
3/12 |
10:10 |
12:00 |
10 |
100 |
计算机接口技术上课 |
课间休息 |
|
14:00 |
15:50 |
10 |
100 |
嵌入式开发技术上课 |
课间休息 |
|
16:50 |
17:50 |
|
60 |
四则运算 |
|
|
22:35 |
23:30 |
|
55 |
四则运算 |
|
3/13 |
8:00 |
12:00 |
40 |
200 |
上课 软件工程 操作系统 |
课间休息 |
|
21:00 |
23:00 |
20 |
100 |
编写四则运算 |
聊天、上厕所 |
3/14 |
12:12 |
12:55 |
|
43 |
优化代码 |
|
缺陷记录日志:
学生 袁佩佩
日期 3/14
教员 王建民
程序号 2
日期 |
编号 |
类型 |
引入阶段 |
排除阶段 |
修复时间 |
修复缺陷 |
15/3/11 |
1 |
|
编码 |
编译 |
2min |
|
描述:实参与形参类型不匹配 |
||||||
3/12 |
2 |
|
编码 |
执行 |
5min |
逻辑错误 |
描述:检查重复的代码没写全,导致没能有效的避免重复。 |
||||||
3/13 |
3 |
|
编码 |
执行 |
5min |
逻辑错误 |
描述:引入数据结构后,原来的参数和变量没有彻底转换完 |
||||||
3/14 |
4 |
|
编码 |
编译 |
1min |
|
描述:忘加右括号了“)” |
五、心得体会
设计思想里已经写了,编写程序的时候,我是渐进式的自顶向下的开发的。但是我不太清楚编写代码时,该不该用自顶向下。因为我比较注重细节,先写框架再写核心往往会导致编出来的程序虎头蛇尾。而且这次我是最后才加上的数据结构,以至于之前写的变量名、参数等等都要变更,有些麻烦。以后我会训练自己自底向上写代码的能力。我有个坏毛病就是,边写边思考,有时候这个问题还差一点就解决了,结果就又扯到另一个问题上了。我在与其他同学交流的过程中,也了解到“下手”之前,必须要先把整个程序在心里构建的差不多了,再敲代码。多和编程能力强或编程习惯好的同学交流,多向他们学习,也是受益匪浅啊。
最后就是,数据结构部分我是借鉴之前数据结构小学期自己做的员工管理系统来编写的,回忆起了链表以及相关操作的知识。