结对开发-1
一、 设计思路:
程序包含两部分,一部分是算式的生成,一部分是栈的使用用来判断和计算结果;
算式生成,用的是调用子函数,因为每一个年级的出题要求不同所以对出题的范围加了条件限制;程序的结构框架大致为:
程序开始将字符串数组宏定义,出题的数量和选择打印的方式都进行宏定义;
For( )
{
For( )
{
a> 产生左括号;(用switch…..case语句来判断;)
b> 产生数字:(其中,可以有分数小数和整数的产生)
其中不同年级选择的范围不同;
c>产生右括号;(右括号的产生是用左括号的数量来限制的)
d>产生运算符;运算符在输出最后一位数字之后就不会执行运算符产生的程序;)
}
}
栈程序中:
将算式生成的string类型的数组,转化为char类型的,读入到栈中,然后利用字符串优先级的判断,计算函数,我们的程序中不能出现负数所以在输出结果时加了结果判断;
1 //组成员:禹慧慧 吕兰兰 2 //四则运算,在前面的基础上实现判断正误 2016.3.19 3 //我们的结果是如果选择dos界面,可以在界面上实现输入结果、判断正误与给出答案;如果选择txt,则打印出一份题目和一份答案 4 //没有控制余数,都算成了小数 5 #include<iostream> 6 #include<ctime> 7 #include<cmath> 8 #include<sstream> 9 #include<string> 10 #include<fstream> 11 #include<iomanip> 12 #define MAX 1000 13 using namespace std; 14 15 int N; 16 int way; 17 string str[1000]; 18 ofstream outfile("questions.txt"); 19 ofstream outfile_1("answers.txt"); 20 21 22 class Input 23 { 24 public: 25 Input() 26 { 27 for( int i = 0;i < MAX;i++ ) 28 Str_input[i] = '\0'; 29 } 30 char Str_input[MAX]; 31 void inStr(string str11) 32 { 33 strcpy(Str_input,str11.c_str()); 34 } 35 }; 36 37 /*输出模块*/ 38 class Output 39 { 40 public: 41 Output() 42 { 43 result = 0; 44 } 45 void getRes( double res ) 46 { 47 result = res; 48 } 49 void printRes(double &num_an) 50 { 51 num_an=result; 52 } 53 private: 54 double result; 55 }; 56 57 /*计算用的存储结构*/ 58 template <class Type> 59 class STACK{ 60 private: 61 Type base[MAX]; 62 int Size; 63 public: 64 STACK() 65 { 66 Size=0; 67 }; 68 void push(Type a) 69 { 70 base[Size]=a; 71 Size++; 72 } 73 Type pop() 74 { 75 return base[--Size]; 76 } 77 int size() 78 {return Size;} 79 }; 80 81 82 /*计算的模块*/ 83 class jisuan 84 { 85 public: 86 bool shuhanshu(char); 87 bool fuhanshu(char); 88 int jckh(char); 89 bool jcxsd(char *); 90 int pdyxj(char); 91 double ToData(char*); 92 double Call(double,double,char); 93 int ppkh(char* buffer,int pos); 94 void Opr( STACK<char>&, STACK<double>&, int& ); 95 double Calculate(char*, double& ); 96 97 }; 98 bool jisuan::shuhanshu(char ch) 99 { 100 return ((ch>='0'&&ch<='9')||ch=='.')?true:false; 101 } 102 bool jisuan::fuhanshu(char ch) 103 { 104 return (ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='#')?true:false; 105 } 106 int jisuan::jckh(char ch) 107 { 108 if(ch=='(') 109 return 1; 110 if(ch==')') 111 return -1; 112 return 0; 113 } 114 bool jisuan::jcxsd(char *ch) 115 { 116 int a=0; 117 for(int i=0;i<strlen(ch);i++) 118 if(ch[i]=='.') 119 a++; 120 if(a>1) 121 return false; 122 return true; 123 } 124 int jisuan::pdyxj(char ch) //符号的优先极别 125 { 126 switch(ch) 127 { 128 case '+': 129 return 0; 130 case '-': 131 return 0; 132 case '*': 133 return 1; 134 case '/': 135 return 1; 136 case '#': 137 return 0; 138 default: 139 return -1; 140 } 141 } 142 double jisuan::ToData(char* ch) //将数字转化为数值 143 { 144 int i,j,sumn=0; 145 double sum=0.0; 146 if(!jcxsd(ch)) return 0.0; 147 for(i=0;i<strlen(ch);i++) 148 { 149 if(ch[i]!='.') 150 sumn=sumn*10+(ch[i]-'0'); 151 else break; 152 } 153 if(i<strlen(ch)) 154 for(j=i+1;j<strlen(ch);j++) 155 sum=sum*10+(ch[j]-'0'); 156 sum /= pow(10.0,(double)(strlen(ch)-1-i)); 157 return (sum+sumn); 158 } 159 double jisuan::Call(double sum,double data,char ch) 160 { 161 double ans=0.0; 162 switch(ch) 163 { 164 case '+': 165 ans=sum+data; 166 break; 167 case '-': 168 ans=sum-data; 169 break; 170 case '*': 171 ans=sum*data; 172 break; 173 case '/': 174 if( data != 0.0 ) 175 ans=sum/data; 176 else 177 { 178 cout<<"程序出现除0错误,终止!\n"; 179 system("pause"); 180 exit(1); 181 } 182 break; 183 case '#': 184 return 0; 185 default:ans=0.0; 186 break; 187 } 188 return ans; 189 } 190 int jisuan::ppkh(char* buffer,int pos) //利用栈找到匹配的括号 191 { 192 STACK<char> Temp; 193 int i; 194 for(i=pos;i<strlen(buffer);i++) 195 { 196 if(jckh(buffer[i])==1) 197 Temp.push('0'); 198 if(jckh(buffer[i])==-1) 199 { 200 Temp.pop(); 201 if(Temp.size()==0) return i; 202 } 203 } 204 return -1; 205 } 206 void jisuan::Opr(STACK<char>& symbol,STACK<double>& data,int& mark) 207 { 208 double sum; 209 while(symbol.size()!=0) 210 { 211 char tem=symbol.pop(); 212 int temp=pdyxj(tem); 213 symbol.push(tem); 214 if(temp<mark) 215 break; 216 else{ 217 sum=Call(data.pop(),data.pop(),symbol.pop()); 218 data.push(sum); 219 } 220 } 221 } 222 double jisuan::Calculate(char* buffer,double& sum) //字符串读入和各个函数调配 223 { 224 STACK<double> data; 225 STACK<char> symbol; 226 double ans; 227 char temp[MAX]; 228 int ct=0,mark=0,tp=0; 229 data.push(sum); 230 while(ct<=strlen(buffer)) 231 { 232 if(shuhanshu(buffer[ct])) //如果是数字或小数点 233 { 234 while( ct < strlen(buffer) && shuhanshu(buffer[ct]) ) 235 temp[tp++]=buffer[ct++]; 236 temp[tp]='\0'; 237 tp=0; //读到非数字也非小数为止 238 ans=ToData(temp); //把读到的字符串转化为数 239 data.push(ans); 240 241 if(ct==strlen(buffer)) //已经独到字符串末尾 242 { 243 mark=0; 244 Opr(symbol,data,mark); 245 sum=data.pop(); 246 return sum; 247 } 248 else{ 249 int mark=pdyxj(buffer[ct]); 250 Opr(symbol,data,mark); //计算 251 } 252 } 253 else if(fuhanshu(buffer[ct])) //如果是运算符 254 symbol.push(buffer[ct++]); //运算符入symbol栈 255 else 256 { 257 char BF[100];int k=0; //如果都不是,则只能是括号 258 while( jckh( buffer[ct] ) != 1 && ct <= strlen(buffer) ) 259 BF[k++] = buffer[ct++]; 260 BF[k]='\0'; 261 if(jckh(buffer[ct])==1) //一旦读到左括号,寻找它匹配的右括号 262 { 263 int i,j; 264 char Temp[100]; 265 for(i=ct+1,j=0;i<ppkh(buffer,ct);i++,j++) 266 Temp[j]=buffer[i]; //把这对括号中的字符串存入Temp 267 Temp[j]='\0'; 268 data.push(Calculate(Temp,sum)); 269 270 ct+=(strlen(Temp)+1); 271 if(ct+1==strlen(buffer)) 272 { 273 mark=0; 274 Opr(symbol,data,mark); 275 sum=data.pop(); 276 return sum; 277 } 278 else 279 { 280 mark=pdyxj(buffer[ct+1]); //不是的话继续计算 281 Opr(symbol,data,mark); 282 } 283 ct++; //读入下一个字符 284 } 285 } 286 } 287 return 0.; 288 } 289 int Expression(int grade,int N) 290 { 291 292 Input in; 293 jisuan cl; 294 Output out; 295 double sum=0.0; 296 double result; 297 double answer; 298 cout.precision(5); 299 int random_a,random_b,random_c,random_e,random_f,random_g; 300 int max,min;//整数 301 int random_d; 302 double random_h; 303 304 //根据年级的不同选择每道题目的数的数量 305 if(grade==2) 306 { 307 random_a=rand()%2+2; 308 max=100; 309 min=1; 310 } 311 if(grade==3) 312 { 313 random_a=rand()%3+2; 314 max=500; 315 min=1; 316 } 317 if(grade==4) 318 { 319 random_a=rand()%3+2; 320 max=1000; 321 min=1; 322 } 323 if(grade==5) 324 { 325 random_a=rand()%3+2; 326 max=10000; 327 min=1; 328 } 329 if(grade==6) 330 { 331 random_a=rand()%3+2; 332 max=10000; 333 min=1; 334 } 335 for(int j=0;j<N;j++) 336 { 337 int flag=0; 338 int count_p=0,count_q=0;//计算括号的数量 339 for(int i=0;i<random_a;i++) 340 { 341 if(grade==2||grade==3||grade==4) 342 { 343 random_b=0;//只有整数计算 344 } 345 if(grade==5||grade==6) 346 { 347 random_b=rand()%3+0; 348 } 349 char str1[100]; 350 if(random_a>2&&i<(random_a-1)) 351 { 352 random_d=rand()%4+0; 353 switch(random_d)//控制括号的产生 354 { 355 case 0:flag=0;break; 356 case 1:if(i!=(random_a-1)&&i<(random_a-2)){str[j]+='(';flag=1;count_q+=1;}break; 357 case 2:flag=0;break; 358 case 3:if(i!=(random_a-1)&&i<(random_a-2)){str[j]+='(';flag=1;count_q+=1;}break; 359 } 360 } 361 //数字的产生 362 switch(random_b) 363 { 364 365 case 0: 366 { 367 random_c=rand()%(max-min+1)+min;//整数 368 itoa(random_c,str1,10); 369 str[j]+=str1; 370 } break; 371 372 case 1: 373 { 374 random_h=(rand()%100)/100.0;//小数 375 random_e=rand()%10+0; 376 random_h+=random_e; 377 stringstream ss; 378 ss<<random_h; 379 str[j]+=ss.str(); 380 } 381 break; 382 case 2: 383 {//分数 384 do{ 385 random_f=rand()%20+1; 386 random_g=rand()%10+1; 387 }while(random_g==random_f); 388 int number=1; 389 int m; 390 if(random_g>random_f) 391 { 392 m=random_f; 393 } 394 else 395 { m=random_g;} 396 for(int k=2;k<m+1;k++) 397 { 398 if((random_g%k==0)&&(random_f%k==0)) 399 { 400 number=k; 401 } 402 } 403 random_f=random_f/number; 404 random_g=random_g/number; 405 str[j]+='('; 406 if(random_g==1) 407 { 408 int n=0; 409 n=random_g; 410 random_g=random_f; 411 random_f=n; 412 } 413 itoa(random_f,str1,10); 414 str[j]+=str1; 415 str[j]+='/'; 416 itoa(random_g,str1,10); 417 str[j]+=str1; 418 str[j]+=')'; 419 }break; 420 } 421 //右括号的产生 422 if((flag!=1)&&(count_p!=count_q)) 423 { 424 str[j]+=')'; 425 count_p+=1; 426 } 427 if(i==(random_a-1)) 428 { 429 if(count_p<count_q) 430 { 431 for(int k=0;k<(count_q-count_p);k++) 432 str[j]+=')'; 433 } 434 } 435 if(i!=(random_a-1)) 436 { 437 random_b=rand()%4+0; 438 switch(random_b) 439 { 440 case 0:{str[j]+='+';}break; 441 case 1:{str[j]+='-';}break; 442 case 2:{str[j]+='*';}break; 443 case 3:{str[j]+='/';}break; 444 } 445 } 446 } 447 448 in.inStr(str[j]); //输入模块 449 out.getRes( cl.Calculate(in.Str_input,sum) ); //计算模块 450 out.printRes(result); 451 if (result<0) 452 { 453 str[j]=""; 454 j--; 455 456 } 457 else 458 { 459 460 if(way==1) 461 { 462 cout<<str[j]<<"="<<endl; 463 cout<<"请输入答案(6位有效数字):"; 464 cin>>answer; 465 466 if (answer==result) 467 { 468 469 cout<<"回答正确!"<<endl; 470 } 471 else 472 { 473 cout<<"回答错误!"<<endl; 474 cout<<"正确结果为:"<<result<<endl; 475 } 476 } 477 else 478 { 479 outfile<<str[j]<<"="; 480 outfile<<endl; 481 outfile_1<<"正确结果为:"/*<<setprecision(5)*/<<result; 482 outfile_1<<endl; 483 } 484 } 485 486 } 487 488 return 0; 489 } 490 491 492 int main() 493 { 494 int grade; 495 srand(time(0)); 496 497 cout<<"********************************************************************************"<<endl; 498 cout<<"***************************欢迎使用小学四则运算出题系统*************************"<<endl; 499 cout<<"********************************************************************************"<<endl; 500 cout<<"*******作者:石家庄铁道大学 信1301-2 禹慧慧 吕兰兰 2016.3.19 *******"<<endl; 501 cout<<"********************************************************************************"<<endl; 502 cout<<"请选择打印方式:(0-TXT,1-DOS):"; 503 cin>>way; 504 cout<<"********************************请选择年级**************************************"<<endl; 505 cout<<" 2年级 "<<endl; 506 cout<<" 3年级 "<<endl; 507 cout<<" 4年级 "<<endl; 508 cout<<" 5年级 "<<endl; 509 cout<<" 6年级 "<<endl; 510 cout<<"********************************************************************************"<<endl; 511 cin>>grade; 512 513 cout<<"请输入题目数量:"; 514 cin>>N; 515 if(grade==2) 516 { 517 Expression(grade,N); 518 } 519 if(grade==3) 520 { 521 Expression(grade,N); 522 } 523 if(grade==4) 524 { 525 Expression(grade,N); 526 } 527 if(grade==5) 528 { 529 Expression(grade,N); 530 } 531 if(grade==6) 532 { 533 Expression(grade,N); 534 } 535 outfile.close(); 536 outfile_1.close(); 537 }
三、 用时:计划花费20个小时,实际花费了23个小时;其中包括改错调试程序; 四、 体会:本次试验又使用了新的知识;子函数的调用和栈的使用以及优先级的判断,这次实验花费的时间很长并且上网和查书找了很多东西。输入输出流的使用,以及栈的优先级的判 断,出栈入栈,计算结果,判断是否有错等。这次实验很有成就感!!!O(∩_∩)O~~
五、程序运行截图:
工作照:
项目计划日志(单位:h):
|
听课 |
编写程序 |
阅读相关书籍 |
网上查找资料 |
日总计 |
周一 |
2 |
0 |
1 |
0 |
3 |
周二 |
0 |
3 |
|
0.5 |
3.5 |
周三 |
0 |
3 |
1 |
0 |
4 |
周四 |
2 |
6 |
|
1 |
9 |
周五 |
0 |
4 |
1 |
1 |
6 |
周六 |
0 |
3 |
|
1 |
4 |
周日 |
|
|
|
|
|
周总计 |
4 |
19 |
3 |
3.5 |
29.5 |
时间记录日志:(单位:min):
日期 |
开始时间 |
结束时间 |
中断时间 |
净时间 |
活动 |
备注 |
星期一 |
14:00 |
15:50 |
10 |
100 |
听课 |
软件工程 |
|
20:00 |
21:00 |
0 |
60 |
看书 |
构建之法 |
星期二 |
19:00 |
19:30 |
0 |
30 |
网上查找资料 |
|
|
20:00 |
23:00 |
0 |
180 |
编程 |
结对编程 |
星期三 |
15:00 |
22:00 |
180 |
240 |
编程和上网查找资料并且调试程序 |
结对编程 |
星期四 |
14:00 |
15:50 |
10 |
100 |
听课 |
软件工程 |
|
16:00 |
23:00 |
60 |
360 |
编程 |
结对编程 |
星期五 |
16:00 |
21:00 |
60 |
240 |
编程上网查找资料 |
结对编程
|
|
21:30 |
22:30 |
0 |
60 |
看书 |
构建之法 |
星期六 |
19:00 |
22:00 |
0 |
180 |
编程和写博客 |
结对编程 |
|
|
|
|
|
|
|
缺陷记录日志:
日期 |
编号 |
类型 |
引入阶段 |
排除阶段 |
修复时间 |
修复缺陷 |
3/17 |
1 |
20 |
编码 |
调试 |
20:00 |
括号输出错误,运算不正确 |
3/18 |
2 |
20 |
编码 |
调试 |
19:00-21:00 |
对栈的编写和运算结果 |
3/19 |
3 |
20 |
编码 |
调试 |
20:00-22:00 |
括号的丢失和语法的错误。 |
组员禹慧慧网址:http://www.cnblogs.com/yhhzxcvbnm/