结对开发——四则运算(三)
一、题目及题目要求
编程随机生成四则运算,算数包括整数和真分数
1.题目避免重复
2.可定制(数量/打印方式)
3.可以控制下列参数:
是否有乘除法;
是否有括号(最多可以支持十个数参与运算);
数值范围;
加减有无负数;
除法有无余数。
4.输入结果并判断正确
二、设计思路
在上次程序的基础上进行修改,
1.题目避免重复:为避免随机数每次相同用了srand函数。
2.可定制出题数量:通过键盘输入数字,在for循环中控制循环次数。
3. 是否有乘除法:把算符分为两大类,利用case语句选择前四种加和减,后四种乘除。
4. 数值范围:在产生随机数时通过输入控制rand函数的参数,从而使运算数不超过此范围。
5. 加减有无负号:结果无负数,判断两操作数,第一操作数若比第二操作数小,则第二个减第一个。
6.除法有无余数:除法无余数,判断第一操作数模第二操作数的结果,若为0即可输出,否则再循环一次。
7.是否有括号:先随机生成一个数字,代表着生成表达式中操作数的个数。再循环生成一个数字,将其输出,然后等概率生成‘+’‘-’‘*’‘/’中的一个跟在该数字后面,输出。以一定概率生成左括号,若生成了左括号则输出,并进行计数标志当前共有多少个未完成匹配的左括号。若当前有未完成匹配的左括号,则在生成一个数字后,生成一个操作符前,以一定的概率生成右括号。在生成完毕后,生成最后一个数并将为匹配的左括号予以匹配。把产生的式子存入文件。
8.输入结果并判断正确:(1)对于两个运算数的式子,把结果存入数组,调用函数与数组中的值比较。
(2)对于多个运算数的式子,从文件中读取内容,利用中缀表达式转换为后缀表达式,然后就是后缀表达式的计算,最后与用户输入结果对比。
三、代码
1 #include<iostream> 2 #include<ctime> 3 #include<stack> 4 #include<fstream> 5 #define length 10000//存放答案数组长度 6 using namespace std; 7 typedef long long ll; 8 ofstream fout("equation.txt"); 9 char Op[] = {'+', '-', '*', '/'}; 10 int rights;//对题数目 11 int wrong;//错题数目 12 13 struct num{ 14 ll numerator, denominator; 15 num(){numerator = 0; denominator = 1;} 16 num(int n) {numerator = n; denominator = 1;} 17 num(int n,int d) {numerator = n; denominator = d;} 18 19 void operator = (num x) 20 { 21 numerator = x.numerator; 22 denominator = x.denominator; 23 } 24 }; 25 #define maxl 1005 26 char nifix[maxl], post[maxl]; 27 char ans[maxl]; 28 int cnt_right, cnt_wrong; 29 bool error; 30 num res, rst; 31 32 //****分数类***// 33 class fraction 34 { 35 private: 36 int above; //分子 37 int below; //分母 38 void reduction(); //约分 39 fraction makeCommond(fraction); //通分 40 41 public: 42 fraction() 43 { //构造函数 44 } 45 fraction add(fraction); //两分数相加 46 fraction sub(fraction); //两分数相减 47 fraction mul(fraction); //两分数相乘 48 fraction div(fraction); //两分数相除 49 int display(int,int); //显示分数 50 void setvalue(int ,int); //存储分数 51 }; 52 53 //***********分数的约分*********// 54 55 void fraction::reduction() 56 { 57 int i,comdiv,small,max; 58 if(above<below) 59 { 60 small=above; 61 max=below; 62 } 63 else 64 { 65 small=below; 66 max=above; 67 } 68 for(i=small;i>1;i--) 69 { 70 if((small%i==0 )&(max%i==0) ) 71 break; 72 } 73 comdiv=i; //最大公约数 74 75 if(i!=0) 76 { 77 above/=i; 78 below/=i; 79 } 80 } 81 82 //*************分数的通分*************// 83 84 fraction fraction::makeCommond(fraction frac) 85 { 86 int b1=below,b2=frac.below, m,s; 87 if(b1>b2) 88 { 89 m=b1%b2; 90 s=b2; 91 } 92 else 93 { 94 m=b2%b1; 95 s=b1; 96 } 97 while(m>0) 98 { 99 int res=s%m; 100 s=m,m=res; 101 } 102 int small=(b1*b2)/s; 103 above=above*(small/below); 104 frac.above=frac.above*(small/frac.below); 105 below=small; 106 frac.below=small; 107 return frac; 108 } 109 //***************分数的相加*************// 110 111 fraction fraction::add(fraction fr) 112 { 113 fraction myFraction; 114 myFraction.above=above*fr.below+fr.above*below; 115 myFraction.below=below*fr.below; 116 myFraction.reduction(); 117 return myFraction; 118 } 119 //*********************分数的相减***************// 120 121 fraction fraction::sub(fraction fr) 122 { 123 fraction myFraction; 124 myFraction.above=above*fr.below-fr.above*below; 125 myFraction.below=below*fr.below; 126 myFraction.reduction(); 127 return myFraction; 128 } 129 130 //*******************分数的相乘****************// 131 132 fraction fraction::mul(fraction fr) 133 { 134 fraction myFraction; 135 myFraction.above=above*fr.above; 136 myFraction.below=below*fr.below; 137 myFraction.reduction(); 138 return myFraction; 139 } 140 //******************分数的相除***********// 141 142 fraction fraction::div(fraction fr) 143 { 144 fraction myFraction; 145 myFraction.above=above*fr.below; 146 myFraction.below=below*fr.above; 147 myFraction.reduction(); 148 return myFraction; 149 } 150 151 //*********************分数答案的输入判断*************// 152 153 int fraction::display(int a,int b) 154 { 155 156 if((a==above)&&(b==below)) 157 { 158 cout<<"正确"<<endl; 159 rights=rights+1; 160 } 161 else 162 { 163 cout<<"错误"<<endl; 164 wrong=wrong+1; 165 } 166 return rights,wrong; 167 } 168 169 //*******************分数的赋值****************// 170 171 void fraction::setvalue(int sj1,int sj3) 172 { 173 above=sj1; 174 below=sj3; 175 } 176 //*************无分数,无余数答案判断****************// 177 178 int answer(int a[],int i) 179 { 180 int ans; 181 182 cout<<"请输入答案:"<<endl; 183 cin>>ans; 184 if(ans==a[i]) 185 { 186 cout<<"正确"<<endl; 187 rights=rights+1; 188 } 189 else 190 { 191 cout<<"错误"<<endl; 192 wrong=wrong+1; 193 } 194 return rights,wrong; 195 196 } 197 //*************无分数,有余数答案判断****************// 198 int answer_1(int a[],int i,int b[]) 199 { 200 int ans,yushu; 201 202 cout<<"请输入商:"<<endl; 203 cin>>ans; 204 cout<<"输入余数"<<endl; 205 cin>>yushu; 206 if((ans==a[i])&&(yushu=b[i])) 207 { 208 cout<<"正确"<<endl; 209 rights=rights+1; 210 } 211 else 212 { 213 cout<<"错误"<<endl; 214 wrong=wrong+1; 215 } 216 return rights,wrong; 217 218 } 219 //*************产生带括号式子****************// 220 void create(int maxn) 221 { 222 223 if(!fout) //如果打开失败,outfile返回值 224 { 225 cerr << "open error!" << endl; 226 exit(1); 227 } 228 229 //首先随机生成算式中操作数的个数,其数量必须大于1 230 int lengt;//式子长度 231 do{ 232 lengt = rand()%8; 233 }while(lengt < 2); 234 bool div = false; //用来防止出现除0错误 235 int brack_cnt = 0; //记录未匹配的左括号个数 236 ll num, op; 237 for (int i = 1; i < lengt; i++) //循环生成算式 238 { 239 if (div) //若此时需要生成的数字前的负号是'/',则需要特判此次生成的数字不能为0 240 { 241 div = false; 242 do{ 243 num = rand()%maxn; 244 }while(num == 0); 245 cout<< num; 246 fout<< num; 247 248 } 249 else 250 { 251 num= rand()%maxn; 252 fout <<num; 253 cout<<num; 254 }//否则直接生成数字输出 255 int tmpcnt = brack_cnt; 256 for (int j = 0; j < tmpcnt; j++) //若当前有未匹配的左括号,则对每一个未匹配的左括号,都有一定概率生成相应右括号。 257 { 258 if ((rand()%5) > 2) //生成右括号概率为0.6 259 { 260 brack_cnt--; 261 262 fout << ")"; 263 cout<<")"; 264 } 265 } 266 267 op = rand()%4; //生成运算符 268 fout << Op[op]; 269 cout << Op[op]; 270 if (op == 3) //若生成了除号,则需要置相应标志位 271 div = true; 272 273 if (!(rand()%3)) //以一定概率生成左括号,概率为1/3 274 { 275 fout << "("; 276 cout<<"("; 277 brack_cnt++; 278 num= rand()%maxn;//生成左括号后必须生成一个数字和运算符,不然可能出现(15)这样的错误 279 fout <<num; 280 cout<<num; 281 op = rand()%4; 282 fout << Op[op]; 283 cout<<Op[op]; 284 if (op == 3) 285 div = true; 286 } 287 } 288 if (div) //生成最后一个数字,该数字后不需要跟运算符 289 { 290 div = false; 291 do{ 292 num = rand()%maxn; 293 }while(num == 0); 294 fout << num; 295 cout<< num; 296 } 297 else 298 { 299 num=rand()%maxn; 300 fout << num; 301 cout<<num; 302 303 } 304 while(brack_cnt--) //补全右括号 305 { 306 fout << ")"; 307 cout << ")"; 308 } 309 cout<<"="; 310 fout<< endl; 311 cout<<endl; 312 313 } 314 bool isNum(char x) //判断是否是数字 315 { 316 return (x >= '0' && x <= '9'); 317 } 318 319 bool isOp(char x) //判断是否是操作符 320 { 321 return (x == '+' || x == '-' || x == '*' || x == '/' || x == '(' || x == ')'); 322 } 323 324 int priority(char x) //返回一个操作符的优先级 325 { 326 if (x == '-' || x == '+') 327 return 1; 328 else if (x == '*' || x == '/') 329 return 2; 330 else if (x == '(') 331 return 0; 332 else 333 return -1; 334 } 335 bool nifix_to_post() 336 { 337 memset(post, 0, sizeof(post)); 338 stack<char> s; //操作符栈,用来压操作符 339 /* ************************************************************************************************ 340 # 由于操作数是多位的,所以我们逐位做一个累加暂存的工作,当遇到操作符时,代表此操作符前的数暂存完毕, 341 # 需要将其入栈,但也不是所有操作符前都有操作数,如'*('等,所以我们需要一个标志位来表示某个操作符前 342 # 是否进行过暂存操作数的处理。 343 *///************************************************************************************************** 344 bool havenum = false; 345 int tmp = 0, pos = 0; //tmp为暂存多位数的变量,pos为后缀数组存储位置 346 for (int i = 0; nifix[i] != '\0'; i++) //循环遍历中缀数组 347 { 348 if (isNum(nifix[i])) //若当前字符是数字,则进行暂存操作。并标识已有操作数 349 { 350 havenum = true; 351 tmp = tmp*10 + (nifix[i]-'0'); 352 } 353 else if (isOp(nifix[i])) //若当前字符是操作符则进行如下操作 354 { 355 //中缀表达式合法性判断,判断是否有连续两个字符相连,若有则代表出错 356 if (isOp(nifix[i-1]) && nifix[i-1] != ')' && nifix[i] != '(') 357 return true; 358 //如果操作符前有操作数,则将得到的操作数输出至后缀表达式 359 if (havenum) 360 { 361 havenum = false; 362 post[pos++] = tmp + '0'; 363 tmp = 0; 364 } 365 //如果操作符为右括号,则按规则进行出栈如后缀表达式等操作 366 if (nifix[i] == ')') 367 { 368 if (s.empty()) //中缀表达式合法性判断,判断括号匹配 369 return true; 370 while(s.top() != '(') 371 { 372 post[pos++] = s.top(); 373 s.pop(); 374 if (s.empty()) //中缀表达式合法性判断,判断括号匹配 375 return true; 376 } 377 s.pop(); 378 } 379 else if (nifix[i] == '(') //如果是左括号则直接入栈 380 s.push(nifix[i]); 381 else //如果是+-*/则按规则操作 382 { 383 while (!s.empty() && priority(nifix[i]) <= priority(s.top())) 384 { 385 post[pos++] = s.top(); 386 s.pop(); 387 } 388 s.push(nifix[i]); 389 } 390 } 391 else //中缀表达式合法性判断,判断是否含非法符号 392 return true; 393 } 394 //若有操作数,则将其输出至后缀表达式 395 if (havenum) 396 { 397 havenum = false; 398 post[pos++] = tmp + '0'; 399 tmp = 0; 400 } 401 //将栈中操作符一次输出到后缀表达式中 402 while(!s.empty()) 403 { 404 if (s.top() == '(') //中缀表达式合法性判断,判断括号匹配 405 return true; 406 post[pos++] = s.top(); 407 s.pop(); 408 } 409 return false; 410 } 411 ll gcd(ll m, ll n) 412 { 413 ll tmp; 414 tmp = m % n; 415 while(tmp) 416 { 417 m = n; 418 n = tmp; 419 tmp = m % n; 420 } 421 return n; 422 } 423 bool cal_result() 424 { 425 stack<num> s; //用来存放操作数的栈 426 for (int i = 0; i < (strlen(post)); i++) //循环遍历后缀表达式 427 { 428 if (!isOp(post[i])) //如果是数字则直接入栈 429 { 430 num tmp(post[i]-'0', 1); 431 s.push(tmp); 432 } 433 else 434 { 435 //取出两个操作数,如果操作数数量不够,则出错,返回 436 if (s.empty()) 437 return true; 438 num b = s.top(); s.pop(); 439 if (s.empty()) 440 return true; 441 num a = s.top(); s.pop(); 442 num c; 443 444 if (post[i] == '+') //操作符是'+',进行上述规则运算 445 { 446 c.numerator = a.numerator * b.denominator + b.numerator * a.denominator; 447 c.denominator = a.denominator * b.denominator; 448 } 449 else if (post[i] == '-') //操作符是'-',进行上述规则运算 450 { 451 c.numerator = a.numerator * b.denominator - b.numerator * a.denominator; 452 c.denominator = a.denominator * b.denominator; 453 } 454 else if (post[i] == '*') //操作符是'*',进行上述规则运算 455 { 456 c.numerator = a.numerator * b.numerator; 457 c.denominator = a.denominator * b.denominator; 458 } 459 else if (post[i] == '/') //操作符是'/',进行上述规则运算 460 { 461 if (b.numerator == 0) //如果除的是0,则出现除法错误,返回 462 return true; 463 c.numerator = a.numerator * b.denominator; 464 c.denominator = a.denominator * b.numerator; 465 } 466 else //其他情况则出错 467 return true; 468 if (c.numerator != 0) //若结果不为0,则对分子分母约分 469 { 470 ll div = gcd(c.denominator, c.numerator); 471 c.denominator /= div; 472 c.numerator /= div; 473 } 474 s.push(c); //将约分后结果入栈 475 } 476 } 477 if (s.size() > 1) //如果所有操作符都进行相应操作数后栈内还有多个元素,则说明出错,返回 478 return true; 479 res = s.top(); //保存结果 480 s.pop(); 481 if (res.denominator < 0) //化简结果,将分母的负号移到分子上 482 { 483 res.numerator = -res.numerator; 484 res.denominator = -res.denominator; 485 } 486 return false; 487 } 488 489 bool trans_ans() 490 { 491 int i = 0; 492 ll tmp = 0; 493 //两个标志位分别标志用户输入的分子分母是否为负数 494 bool num_flag = false, deno_flag = false; 495 //先判断分子是否为负 496 if (ans[i] == '-') 497 { 498 num_flag = true; 499 i++; 500 } 501 //接收第一个数字 502 while(isNum(ans[i])) 503 { 504 tmp = tmp * 10 + (ans[i] - '0'); 505 i++; 506 } 507 //若第一个数为负数,则将转化过来的整数取负 508 if (num_flag) 509 tmp = -tmp; 510 //保存分子 511 rst.numerator = tmp; 512 //分母赋初值为1 513 rst.denominator = 1; 514 tmp = 0; 515 //判断是否是分数 516 if (ans[i] == '/') 517 { 518 //判断分母是否为负数 519 if (ans[++i] == '-') 520 { 521 deno_flag = true; 522 i++; 523 } 524 //接收第二个数 525 while(isNum(ans[i])) 526 { 527 tmp = tmp * 10 + (ans[i] - '0'); 528 i++; 529 } 530 //若第二个数为负数,则将转化过来的整数取负 531 if (deno_flag) 532 tmp = -tmp; 533 //保存分母 534 rst.denominator = tmp; 535 } 536 //若分母为0,则用户输入的结果是非法的 537 if (rst.denominator == 0) 538 return true; 539 //若此时没有遍历所有的字符,则说明输入是非法的 540 if (i != strlen(ans)) 541 return true; 542 //化简分母的负号,将其移至分子 543 if (rst.denominator < 0) 544 { 545 rst.numerator = -rst.numerator; 546 rst.denominator = -rst.denominator; 547 } 548 //若用户输入的分子分母都是负数,则用户输入不符合规范,我们取分母为0(因为计算结果不可能出现分母为0的状况)标志这种情况的发生 549 if (num_flag && deno_flag) 550 rst.denominator = 0; 551 return false; 552 } 553 554 555 int main() 556 { 557 fraction frac,frac2; 558 int sj1,sj2,sf=1,sj3,sj4,r,j=1;//定义随机数及算符 559 int above,below; 560 int Num;//题的数量 561 int numchose;//运算数选择 562 char sfchose;//算符选择 563 char yschose;//余数选择 564 char jf;//减法结果选择 565 int qznum;//取值范围 566 int ans_2[length];//存放正确的答案 567 int ans_4[length]={0};//存放正确的余数 568 srand((unsigned)time(NULL)); //srand函数是以现在系统时间作为时间种子产生随机数 569 cout<<"*****欢迎使用自动出题系统*****"<<endl; 570 cout<<"请对以下内容进行初始化设置:"<<endl; 571 cout<<"请选择运算数(1.二个运算数 2.多个运算数)"<<endl; 572 cin>>numchose; 573 if(numchose==1) 574 { 575 cout<<"请输入打印题数:"<<endl; 576 cin>>Num; 577 cout<<"请选择是否有乘除法?(y/n)"<<endl; 578 cin>>sfchose; 579 cout<<"请输入一个值确定算式中数值取值范围:"<<endl; 580 cin>>qznum; 581 cout<<"减法结果中出现负数吗?(y/n)"; 582 cin>>jf; 583 584 if(sfchose=='y') 585 { 586 cout<<"请选择除法有无余数?(y/n)"<<endl; 587 cin>>yschose; 588 } 589 cout<<"********************************"<<endl; 590 591 for(int i=0;i<Num;i++) 592 { 593 sj1=rand()%qznum; 594 sj2=rand()%qznum; 595 sj3=rand()%qznum; 596 sj4=rand()%qznum; 597 if(sfchose=='n')//无乘除法 598 { 599 sf=rand()%4; 600 } 601 if(sfchose=='y')//有乘除法 602 { 603 sf=rand()%8; 604 } 605 switch(sf) 606 { 607 case 0: 608 cout<<sj1<<"+"<<sj2<<"= "<<endl; 609 ans_2[i]=sj1+sj2; 610 answer(ans_2,i); 611 612 break; 613 case 1: 614 if(jf=='n')//无负数 615 { 616 if(sj1<sj2) 617 { 618 cout<<sj2<<"-"<<sj1<<"= "<<endl; 619 ans_2[i]=sj2-sj1; 620 answer(ans_2,i); 621 622 } 623 else 624 { 625 cout<<sj1<<"-"<<sj2<<"= "<<endl; 626 ans_2[i]=sj1-sj2; 627 answer(ans_2,i); 628 } 629 } 630 else 631 { 632 cout<<sj1<<"-"<<sj2<<"= "<<endl; 633 ans_2[i]=sj1-sj2; 634 answer(ans_2,i); 635 636 } 637 break; 638 case 2: 639 if(sj1>sj3) 640 { 641 r=sj1; 642 sj1=sj3; 643 sj3=r; 644 } 645 if(sj2>sj4) 646 { 647 r=sj2; 648 sj2=sj4; 649 sj4=r; 650 } 651 cout<<"("<<sj1<<"/"<<sj3<<")"<<"+"<<"("<<sj2<<"/"<<sj4<<")= "<<endl; 652 frac.setvalue(sj1,sj3); 653 frac2.setvalue(sj2,sj4); 654 cout<<"输入分子和分母(用空格隔开,结果化到最简)"; 655 cin>>above>>below; 656 frac.add(frac2).display(above,below); 657 658 break; 659 case 3: 660 if(sj1>sj3) 661 { 662 r=sj1; 663 sj1=sj3; 664 sj3=r; 665 } 666 if(sj2>sj4) 667 { 668 r=sj2; 669 sj2=sj4; 670 sj4=r; 671 } 672 if(jf=='n')//减法结果无负数 673 { 674 if((sj1/sj3)<(sj2/sj4)) 675 { 676 cout<<"("<<sj2<<"/"<<sj4<<")"<<"-"<<"("<<sj1<<"/"<<sj3<<")= "<<endl; 677 frac.setvalue(sj2,sj4); 678 frac2.setvalue(sj1,sj3); 679 cout<<"输入分子和分母(用空格隔开,结果化到最简)"; 680 cin>>above>>below; 681 frac.sub(frac2).display(above,below); 682 683 } 684 else 685 { 686 cout<<"("<<sj1<<"/"<<sj3<<")"<<"-"<<"("<<sj2<<"/"<<sj4<<")= "<<endl; 687 frac.setvalue(sj1,sj3); 688 frac2.setvalue(sj2,sj4); 689 cout<<"输入分子和分母(用空格隔开,结果化到最简)"; 690 cin>>above>>below; 691 frac.sub(frac2).display(above,below); 692 } 693 } 694 else 695 { 696 cout<<"("<<sj1<<"/"<<sj3<<")"<<"-"<<"("<<sj2<<"/"<<sj4<<")= "<<endl; 697 frac.setvalue(sj1,sj3); 698 frac2.setvalue(sj2,sj4); 699 cout<<"输入分子和分母(用空格隔开,结果化到最简)"; 700 cin>>above>>below; 701 frac.sub(frac2).display(above,below); 702 } 703 break; 704 case 4: 705 cout<<sj1<<"*"<<sj2<<"="<<endl; 706 ans_2[i]=sj1*sj2; 707 answer(ans_2,i); 708 break; 709 case 5: 710 if(sj2==0)//分母为零则不计入总数 711 { 712 i=i-1; 713 714 } 715 else if(yschose=='n')//除法没有余数 716 { 717 if(sj1%sj2==0) 718 { 719 cout<<sj1<<"/"<<sj2<<"="<<endl; 720 ans_2[i]=sj1/sj2; 721 answer(ans_2,i); 722 723 724 } 725 else 726 { 727 i=i-1; 728 729 } 730 } 731 else if(yschose=='y')//除法有余数 732 { 733 if(sj1%sj2!=0) 734 { 735 cout<<sj1<<"/"<<sj2<<"="<<endl; 736 ans_2[i]=sj1/sj2; 737 ans_4[i]=sj1-sj2*ans_2[i]; 738 answer_1(ans_2,i,ans_4); 739 740 } 741 else 742 { 743 i=i-1; 744 745 } 746 747 } 748 break; 749 case 6: 750 if(sj1>sj3) 751 { 752 r=sj1; 753 sj1=sj3; 754 sj3=r; 755 } 756 if(sj2>sj4) 757 { 758 r=sj2; 759 sj2=sj4; 760 sj4=r; 761 } 762 cout<<"("<<sj1<<"/"<<sj3<<")"<<"*"<<"("<<sj2<<"/"<<sj4<<")= "<<endl; 763 frac.setvalue(sj1,sj3); 764 frac2.setvalue(sj2,sj4); 765 cout<<"输入分子和分母(用空格隔开,结果化到最简)"; 766 cin>>above>>below; 767 frac.mul(frac2).display(above,below); 768 break; 769 case 7: 770 if(sj1>sj3) 771 { 772 r=sj1; 773 sj1=sj3; 774 sj3=r; 775 } 776 if(sj2>sj4) 777 { 778 r=sj2; 779 sj2=sj4; 780 sj4=r; 781 } 782 cout<<"("<<sj1<<"/"<<sj3<<")"<<"/"<<"("<<sj2<<"/"<<sj4<<")= "<<endl; 783 frac.setvalue(sj1,sj3); 784 frac2.setvalue(sj2,sj4); 785 cout<<"输入分子和分母(用空格隔开,结果化到最简)"; 786 cin>>above>>below; 787 frac.div(frac2).display(above,below); 788 break; 789 default: 790 break; 791 } 792 } 793 cout<<"共做对 "<<rights<<" 道题"<<endl; 794 cout<<"共做错 "<<wrong<<" 道题"<<endl; 795 } 796 else 797 { 798 799 cout<<"请输入出题数目:"; 800 cin >>Num ; 801 cout<<"请输入一个值确定算式中数值取值范围:"<<endl; 802 cin>>qznum; 803 cout<<"******************************************"<<endl; 804 while(Num--) 805 { 806 create(qznum); 807 } 808 //计数器请0 809 cnt_right = cnt_wrong = 0; 810 ifstream infile; 811 infile.open("equation.txt", ios::in); 812 if(infile.is_open() == false) 813 { 814 cerr << "open error!" << endl; 815 exit(1); 816 } 817 818 while( infile >> nifix) 819 { 820 error = nifix_to_post(); //中缀转后缀,并接受错误信息 821 if (error) //若过程出错,则输出错误信息 822 { 823 cout << "读取式子出错!" << endl; 824 return 0; 825 } 826 827 //test_post(); 828 829 error = cal_result(); //后缀表达式计算,并接受错误信息 830 if (error) //若过程出错,则输出错误信息 831 { 832 cout << "计算中出错..." << endl; 833 return 0; 834 } 835 836 cout << "请输入答案: "; 837 cin >> ans; //接受用户答案 838 error = trans_ans(); //答案翻译, 并接受错误信息 839 if (error) //若过程出错,则输出错误信息 840 { 841 cout << "输入不合法答案!" << endl; 842 return 0; 843 } 844 //若用户输入和城西计算答案的分子分母相等或分子均为0,则说明用户输入答案正确 845 if ((rst.denominator == res.denominator && rst.numerator == res.numerator) || (rst.numerator == res.numerator && rst.numerator == 0)) 846 { 847 cnt_right++; 848 cout << "正确!" << endl; 849 } 850 //否则答案错误,程序输出正确答案 851 else 852 { 853 cnt_wrong++; 854 cout << "错误. 答案是 "; 855 if (res.denominator == 1) 856 cout << res.numerator << "." << endl; 857 else 858 cout << res.numerator << "/" << res.denominator << "." << endl; 859 } 860 } 861 cout << "统计结果..." << endl; 862 //输出统计结果 863 cout << "你答了" << cnt_right+cnt_wrong << " 道题 "; 864 cout << "正确数:" << cnt_right << " 错误数: " << cnt_wrong << " 。" << endl; 865 infile.close(); 866 867 } 868 869 return 0; 870 }
四、运行截图
五、项目计划日志
日期&&任务 | 听课 | 编写程序 | 阅读相关书籍 | 网上查找资料 | 日总计 |
周一 | 100 | 30 | 20 | 150 | |
周二 | 120 | 30 | 30 | 180 | |
周三 | 30 | 30 | 10 | 70 | |
周四 | 100 | 20 | 30 | 150 | |
周五 | 120 | 30 | 30 | 180 | |
周六 | 45 | 30 | 10 | 85 | |
周日 | 30 | 20 | 50 | ||
周总计 | 200 | 335 | 210 | 120 |
865 |
时间记录日志
3/14
日期 | 开始时间 | 结束时间 | 中断时间 | 净时间 | 活动 | 备注 |
3/14 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程上课 |
21:00 | 21: 30 | 30 | 阅读书籍 | 《构建之法》 | ||
22:10 | 22: 30 | 20 | 网上查找资料 | |||
3/15 | 21:00 | 21:30 | 20 | 120 | 编写程序 | 结对开发-四则运算3 |
22: 15 | 22: 25 | 30 | 网上查找资料 | |||
22:30 | 23:00 | 30 | 阅读书籍 | 《构建之法》 | ||
3/16 | 19: 24 | 20: 00 | 6 | 30 | 编写程序 | 结对开发-四则运算3 |
22:00 | 22: 30 | 30 | 阅读书籍 | 《构建之法》 | ||
22:40 | 22: 50 | 10 | 查找资料 | |||
3/17 | 14:00 | 15: 50 | 100 | 上课 | 软件工程上课 | |
18:00 | 18: 20 | 20 | 编写程序 | 结对开发-四则运算3 | ||
22:00 | 22:30 | 30 | 阅读书籍 | 《构建之法》 | ||
3/18 | 14: 00 | 16: 20 | 20 | 120 | 编写程序 | 结对开发-四则运算3 |
11:23 | 12: 00 | 7 | 30 | 网上查找资料 | ||
21:00 | 21:30 | 30 | 阅读书籍 | 《构建之法》 | ||
3/19 | 9: 00 | 9: 30 | 50 | 30 | 阅读书籍 | 《构建之法》 |
10: 00 | 11: 00 | 15 | 45 | 编写程序 | 结对开发-四则运算3 | |
9: 45 | 9: 55 | 10 | 网上查找资料 | |||
3/20 | 9:00 | 9: 30 | 23 | 30 | 阅读书籍 | 《构建之法》 |
14:50 | 15: 10 | 20 | 网上查找资料 |
缺陷记录日志
日期 | 编号 | 类型 | 引入阶段 | 排除阶段 | 修复时间 | 备注 |
3/18 | 1 | 20 | 编码 | 编译 | 5 | 文件关闭出现错误 |
3/18 | 2 | 20 | 编码 | 编译 | 1 | 变量未初始化 |
3/18 | 3 | 20 | 编码 | 编译 | 3 | 定义了相同名字的变量 |
同组伙伴博客:http://www.cnblogs.com/qizhonh/
工作照: