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