四则运算3
第一次真正意义上的结对编程,感觉还需要磨合。我们拿到这个题目,首先主要是对四则运算2的计算结果进行编程,在可以生成算式的结果上进行编程。我们考虑到用栈来实现表达式求值。首先将栈的一些函数进行编写,比如,出栈入栈函数,获取栈顶元素函数。然后给+、-、*、/、(、)、#列一个优先级表,根据表达式求值的算法。
1.建立并初始化OPTR和OPND栈,分别存放符号和数字。
2.依次取表达式的每个值和符号,执行3-5,知道求出最后的值。
3.去除optr栈顶元素,与都入的进行比较,当读入#时,求解完毕。
4.栈顶元素是数字,压opnd栈
5.如果是符号,将符号与optr栈顶元素进行比较,如果小于,将符号压入optr,如果大于,optr出栈,做相应运算,然后将计算结果压入opnd栈,如果等于,optr栈顶元素为(,读入字符为),这时候optr出栈,继续读取下一个字符。
根据这个算法,我们也遇到了很多问题:
第一,我们将其调试,成功的第一步是能够运算10以内的四则运算,但是若两位数呢。
第二,我们将程序进行改进,把char类型换为double类型,然后建立了三个数组,double a[],char b[],int clu[],分别存放操作数,运算符和对应位置应该是什么(clu[0]=1,表示第一个应该是一个数,clu[1]=2,表示此时应该为一个符号),这样就能是操作数不再局限于一位数了。
第三,程序可以了以后,我们又将程序编程一个字符串,将字符串分开存到三个数组里,在进行运算。根据clu数组的值,在数组a[],b[]进行取值,并运算。
程序代码:
1 /* 2 结对编程《四则运算》 3 于磊 20133078 4 李萌 20133079 */ 5 #include <iostream> 6 #include <string> 7 #include <ctime> 8 #define N 50 9 using namespace std; 10 void Operands_1() /*产生操作数 (-9 -- 9)除0*/ 11 { 12 while(int f=1) 13 { 14 int Oper=rand()%19-9; 15 if(Oper>0) /*没有0*/ 16 { 17 cout<<Oper; 18 break; 19 } 20 if(Oper<0) 21 { 22 cout<<"("<<Oper<<")"; 23 break; 24 } 25 } 26 } 27 void Operands_2()/*-9到9 有0*/ 28 { 29 while(int f=1) /*产生操作数 (-9 -- 9)*/ 30 { 31 int Oper=rand()%19-9; 32 if(Oper>=0)/*有0*/ 33 { 34 cout<<Oper; 35 break; 36 } 37 else 38 { 39 cout<<"("<<Oper<<")"; 40 break; 41 } 42 } 43 } 44 int Operands_3() /*0-9*/ 45 { 46 int Operand=rand()%9+1; 47 return Operand; 48 } 49 string Operands_4() 50 { 51 string s=""; 52 int Operand=rand()%99+1; 53 if(Operand<10) 54 { 55 s+=Operand+48; 56 } 57 else 58 { 59 s+=Operand/10+48; 60 s+=Operand%10+48; 61 } 62 return s; 63 } 64 void Operator_1(string &formula)/*随机产生运算符 有乘除*/ 65 { 66 int f=rand()%4; 67 if(f==0) 68 { 69 formula+="+"; 70 } 71 if(f==1) 72 { 73 formula+="-"; 74 } 75 if(f==2) 76 { 77 formula+="*"; 78 } 79 if(f==3) 80 { 81 formula+="/"; 82 } 83 } 84 void Operator_2(string &formula)/*随机产生运算符 无乘除*/ 85 { 86 int f=rand()%2; 87 if(f==0) 88 { 89 formula+="+"; 90 } 91 if(f==1) 92 { 93 formula+="-"; 94 } 95 } 96 int Bracket_l(int left,string &formula) /*随机产生左括号*/ 97 { 98 int f=rand()%3; 99 if(f<2) 100 { 101 return left; 102 } 103 if(f==2) 104 { 105 formula+="("; 106 return left+1; 107 } 108 return 0; 109 } 110 int Bracket_r(int right,string &formula) /*随机产生右括号*/ 111 { 112 int r=rand()%5; 113 if(r==0) 114 { 115 return right; 116 } 117 if(r>0) /*产生右括号的概率大 */ 118 { 119 formula+=")"; 120 return right+1; 121 } 122 return 0; 123 } 124 string Way_1() /*最多可支持10个数参与计算 有乘除 有括号 10以内 加减有负数 除法有余数*/ 125 { 126 string formula=""; 127 int length=rand()%9+2; /*随机产生表达式中操作数的个数 2-10 个*/ 128 int left=0,right=0,flag=0,left_1; 129 for(int i=0;i<length-1;i++) 130 { 131 left_1=left; 132 left=Bracket_l(left,formula); 133 if(left_1!=left) /*产生了左括号 flag=i*/ 134 { 135 flag=i; 136 } 137 //cout<<Operands_3(); 138 formula+=Operands_4(); 139 if(left>right&&flag!=i) /*左括号大于右括号的个数 and 产生左括号和右括号不在一个循环里 即不会产生“(随机数)” 这种无效情况*/ 140 { 141 right=Bracket_r(right,formula); 142 } 143 Operator_1(formula); /*有乘除*/ 144 } 145 // cout<<Operands_3(); /*因为 一个操作数一个运算符 还缺少一个操作数 (0 -- 9)*/ 146 formula+=Operands_4(); 147 for(int i=0;i<left-right;i++) 148 { 149 //cout<<")"; 150 formula+=")"; 151 } 152 // cout<<" = "<<endl; 153 return formula+="#"; 154 } 155 156 string Way_2() /*最多可支持10个数参与计算 没乘除 有括号 10以内 加减有负数 除法有余数*/ 157 { 158 string formula=""; 159 int length=rand()%9+2; /*随机产生表达式中操作数的个数 2-10 个*/ 160 int left=0,right=0,flag=0,left_1; 161 for(int i=0;i<length-1;i++) 162 { 163 left_1=left; 164 left=Bracket_l(left,formula); 165 if(left_1!=left) /*产生了左括号 flag=i*/ 166 { 167 flag=i; 168 } 169 //cout<<Operands_3(); 170 formula+=Operands_4(); 171 if(left>right&&flag!=i) /*左括号大于右括号的个数 and 产生左括号和右括号不在一个循环里 即不会产生“(随机数)” 这种无效情况*/ 172 { 173 right=Bracket_r(right,formula); 174 } 175 Operator_2(formula); /*有乘除*/ 176 } 177 // cout<<Operands_3(); /*因为 一个操作数一个运算符 还缺少一个操作数 (0 -- 9)*/ 178 formula+=Operands_4(); 179 for(int i=0;i<left-right;i++) 180 { 181 formula+=")"; 182 } 183 return formula+="#"; 184 } 185 string Way_3() /*最多可支持10个数参与计算 没乘除 有括号 10以内 加减有负数 除法有余数*/ 186 { 187 string formula=""; 188 int length=rand()%9+2; /*随机产生表达式中操作数的个数 2-10 个*/ 189 int left=0,right=0,flag=0; 190 for(int i=0;i<length-1;i++) 191 { 192 formula+=Operands_4(); 193 Operator_1(formula); /*有乘除*/ 194 } 195 // 因为 一个操作数一个运算符 还缺少一个操作数 (0 -- 9)*/ 196 formula+=Operands_4(); 197 return formula+="#"; 198 } 199 string Way_4() /*最多可支持10个数参与计算 没乘除 没括号 10以内 加减有负数 除法有余数*/ 200 { 201 string formula=""; 202 int length=rand()%9+2; /*随机产生表达式中操作数的个数 2-10 个*/ 203 int left=0,right=0,flag=0; 204 for(int i=0;i<length-1;i++) 205 { 206 formula+=Operands_4(); 207 Operator_2(formula); /*有乘除*/ 208 } 209 // 因为 一个操作数一个运算符 还缺少一个操作数 (0 -- 9)*/ 210 formula+=Operands_4(); 211 return formula+="#"; 212 } 213 //***************************************************************************** 214 double jisuan(double x,double y,char oper) 215 { 216 switch(oper) 217 { 218 case '+': 219 { 220 return x+y; 221 break; 222 } 223 case '-': 224 { 225 return x-y; 226 break; 227 } 228 case '*': 229 { 230 return x*y; 231 break; 232 } 233 case '/': 234 { 235 return x/y; 236 break; 237 } 238 } 239 return 0; 240 } 241 242 typedef struct{ 243 double *base; 244 double *top; 245 int stacksize; 246 }SqStack; 247 //初始化化栈 248 double InitStack(SqStack &S) 249 { 250 S.base=new double[N]; 251 if(!S.base) 252 exit(0); 253 S.top=S.base; 254 S.stacksize=N; 255 return 1; 256 } 257 258 //入栈操作代码 259 char push(SqStack &S,char s) 260 { 261 if(S.top-S.base==S.stacksize) 262 return 0; 263 *S.top=s; 264 S.top++; 265 return s; 266 } 267 268 double push1(SqStack &S,double s) 269 { 270 if(S.top-S.base==S.stacksize) 271 return 0; 272 *S.top=s; 273 S.top++; 274 return s; 275 } 276 //出栈操作代码 277 char pop(SqStack &S) 278 { 279 char x; 280 if(S.top==S.base) 281 return 0; 282 --S.top; 283 x=*S.top; 284 return x; 285 } 286 287 double pop1(SqStack &S) 288 { 289 double x; 290 if(S.top==S.base) 291 return 0; 292 --S.top; 293 x=*S.top; 294 return x; 295 } 296 //取栈顶元素 297 double GetTop(SqStack S) 298 { 299 if(S.top==S.base) 300 exit(1); 301 return *(S.top-1); 302 } 303 304 char precede(char ch1,char ch2) 305 { 306 int i,j; 307 char a[7][7]={ //优先级对照表,依次为+ - * / ( ) # 308 // + - * / ( ) # 309 '>','>','<','<','<','>','>', // + 310 '>','>','<','<','<','>','>', // - 311 '>','>','>','>','<','>','>', // * 312 '>','>','>','>','<','>','>', // / 313 '<','<','<','<','<','=','0', // ( 314 '>','>','>','>','0','>','>', // ) 315 '<','<','<','<','<','0','=' // # 316 }; 317 switch(ch1) 318 { 319 //优先级与矩阵匹配 320 case '+': 321 { 322 i=0; 323 break; 324 } 325 case '-': 326 { 327 i=1; 328 break; 329 } 330 case '*': 331 { 332 i=2; 333 break; 334 } 335 case '/': 336 { 337 i=3; 338 break; 339 } 340 case '(': 341 { 342 i=4; 343 break; 344 } 345 case ')': 346 { 347 i=5; 348 break; 349 } 350 case '#': 351 { 352 i=6; 353 break; 354 } 355 } 356 switch(ch2) 357 { 358 //优先级与矩阵匹配 359 case '+': 360 { 361 j=0; 362 break; 363 } 364 case '-': 365 { 366 j=1; 367 break; 368 } 369 case '*': 370 { 371 j=2; 372 break; 373 } 374 case '/': 375 { 376 j=3; 377 break; 378 } 379 case '(': 380 { 381 j=4; 382 break; 383 } 384 case ')': 385 { 386 j=5; 387 break; 388 } 389 case '#': 390 { 391 j=6; 392 break; 393 } 394 } 395 return a[i][j]; 396 } 397 398 double calculate(string str) 399 { 400 int i=0,j=0,k=0,w=0; 401 int s=str.length(); 402 double a[N]={0}; 403 char b[N]={0}; 404 int clu[N]={0}; 405 for(k=0;k<s;) 406 { 407 if(str[k]>='0'&&str[k]<='9') 408 { 409 while(str[k]>='0'&&str[k]<='9') 410 { 411 a[i]=(a[i])*10+(str[k]-48); 412 k++; 413 } 414 i++; 415 clu[w]=1; 416 w++; 417 } 418 else 419 { 420 b[i]=str[k]; 421 k++; 422 i++; 423 clu[w]=2; 424 w++; 425 } 426 } 427 double result; 428 i=0; 429 SqStack optr,opnd; 430 InitStack(optr); 431 push(optr,'#'); 432 InitStack(opnd); 433 push(opnd,'#'); 434 while(clu[i]!=0&&b[i]!='#'||GetTop(optr)!='#'&&i<s) 435 { 436 if(clu[i]==1) 437 { 438 push1(opnd,a[i]); 439 //cin>>ch; 440 i++; 441 } 442 else 443 switch(precede(GetTop(optr),b[i])){ 444 case '<': 445 { 446 push(optr,b[i]); 447 i++; 448 break; 449 } 450 case '>': 451 { 452 double y=pop1(opnd); 453 double x=pop1(opnd); 454 char ch=pop(optr); 455 result=jisuan(x,y,ch); 456 push1(opnd,result); 457 break; 458 } 459 case '=': 460 { 461 pop(optr); 462 i++; 463 break; 464 } 465 } 466 } 467 return result; 468 } 469 //******************************************************** 470 int main() /*主函数*/ 471 { 472 srand((unsigned)time(0)); 473 int number=0,a,b; 474 cout<<"------------------------------四则运算---------------------------------"<<endl; 475 cout<<"是否有乘除:是1否0:"; 476 cin>>a; 477 while(a!=0&&a!=1) 478 { 479 cout<<"输入有误!!!请重新输入:"; 480 cin>>a; 481 } 482 cout<<"是否有括号:是1否0:"; 483 cin>>b; 484 while(b!=0&&b!=1) 485 { 486 cout<<"输入有误!!!请重新输入:"; 487 cin>>b; 488 } 489 if(a==1&&b==1) 490 cout<<"最多可支持10个数参与计算 有乘除 有括号 100以内 加减有负数 除法有余数"<<endl; 491 if(a==0&&b==1) 492 cout<<"最多可支持10个数参与计算 无乘除 有括号 100以内 加减有负数 除法有余数"<<endl; 493 if(a==1&&b==0) 494 cout<<"最多可支持10个数参与计算 有乘除 无括号 100以内 加减有负数 除法有余数"<<endl; 495 if(a==0&&b==0) 496 cout<<"最多可支持10个数参与计算 无乘除 无括号 100以内 加减有负数 除法有余数"<<endl; 497 cout<<"-----------------------------------------------------------------------"<<endl; 498 cout<<"请输入题目的数量:"; 499 int nu; 500 cin>>nu; 501 for(int num=0;num<nu;num++) 502 { 503 string s; 504 if(a==1&&b==1) 505 { 506 cout<<num+1<<"、"; 507 s=Way_1(); 508 } 509 if(a==0&&b==1) 510 { 511 cout<<num+1<<"、"; 512 s=Way_2(); 513 } 514 if(a==1&&b==0) 515 { 516 cout<<num+1<<"、"; 517 s=Way_3(); 518 } 519 if(a==0&&b==0) 520 { 521 cout<<num+1<<"、"; 522 s=Way_4(); 523 } 524 for(int i=0;i<s.length()-1;i++) 525 { 526 cout<<s[i]; 527 } 528 cout<<"="; 529 double a; 530 cin>>a; 531 if(a==calculate(s)) 532 { 533 cout<<"---恭喜你!回答正确!"<<endl; 534 number++; 535 } 536 else 537 { 538 cout<<"---很遗憾!回答错误!正确答案为:"<<calculate(s)<<endl; 539 } 540 } 541 cout<<"-----------------------------------------------------------------------"<<endl; 542 cout<<"\t\t您一共做对了"<<number<<"道题! 所得分数为__"<<100/nu*number<<"分__"<<endl; 543 cout<<endl; 544 return 0; 545 }
运行结果:
无括号,无乘除:
有括号,有乘除:
无乘除,有括号:
实验结果表明,要想做对一道这样的四则运算,必须要有耐心和勇气,并且带有乘除的无法保证其整出,算对带有出发的只能靠运气,有待优化。
项目计划总结:
日期\任务 | 听课 | 编写程序 | 查阅资料 | 日总计 |
星期一 | 2 | 1 | 3 | |
星期二 | 2 | 2 | ||
星期三 | 5 | 5 | ||
星期四 | 2 | 1 | 3 | |
星期五 | 3 | 3 | ||
星期六 | 4 | 4 | ||
星期日 | ||||
周总计 | 4 | 14 | 2 |
20 |
时间记录日志:
日期 | 开始 | 结束 | 中断 | 总时间 | 具体活动 | 备注 |
3/14 | 14:00 | 15:50 | 30 | 110 | 听课 | 软件工程 |
16:00 | 17:00 | 无中断 | 60 | 查阅数据结构资料 | 查资料 | |
3/15 | 16:10 | 18:10 | 10 | 110 | 编写程序 | 栈的基本操作编写 |
3/16 | 15:10 | 16:10 | 无中断 | 80 | 编程序 | char类型输入,10以内运算 |
18:00 | 19:10 | 无中断 | 70 | 编写程序 | 将产生式子与计算结果的代码结合,完成正误判断 | |
19:30 | 22:30 | 30 | 150 | 编写程序 | 修复char与int之间的转换bug | |
3/17 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程 |
3/18 | 19:00 | 23:30 | 30 | 240 | 编程序 | char->double转换,完成多位数的计算 |
3/19 | 7:30 | 9:40 | 10 | 120 | 代码整合,找bug | |
9:40 | 10:40 | 60 | 1040min | 调试+博客 | 写博客 |
缺陷记录日志:
日期 | 编号 | 引入阶段 | 排除阶段 | 修复时间&问题描述 |
3/14 | ||||
3/15 | 1 | 编码 | 编译 | 栈的操作返回值类型出现问题,将其转换为char |
3/16 | 2 | 编码 | 编译 | 修复char与int之间的转换bug |
3/17 | 3 | 编码 | 编译 | char->double转换,修复小数的bug |
3/18 | 4 | 编码 | 编译 | 只能一位数的运算,添加了三个数组,解决这个bug |
3/19 | 4 | 调试 | 修复 | 解决用户输入问题,然后判断正误 |
我们的结对照片:
小伙伴的博客链接:http://www.cnblogs.com/L-Damon-v/