四则运算题3
基本设计思路:
1.引入数据结构,对混合四则运算式进行求解;
2.在四则运算题2的基础上添加,计算功能;
3.将计算式保存至文本;
4.将运算式正确结果与输入结果进行对比,判断正误;
5.将答题情况进行统计;
遇到困难:
1.对混合四则运算式进行求解时,需要用到之前学过的数据结构相关知识,很难!
2.分式的计算结果判断问题,最后选择对无限小数进行保留两位的方法。
队员:王楗 http://home.cnblogs.com/u/wangjianly/
结对编程,合作照:
1 //四则运算3 2 //成员:张勋 王楗 3 #include <iostream> 4 #include <fstream> 5 #include <string> 6 #include <cmath> 7 #include <sstream> 8 #include <time.h> 9 using namespace std; 10 11 #define true 1 12 #define false 0 13 #define OPSETSIZE 8 14 15 typedef int Status; 16 unsigned char Prior[8][8] = 17 { // 运算符优先级表 18 // '+' '-' '*' '/' '(' ')' '#' '^' 19 /*'+'*/'>', '>', '<', '<', '<', '>', '>', '<', 20 /*'-'*/'>', '>', '<', '<', '<', '>', '>', '<', 21 /*'*'*/'>', '>', '>', '>', '<', '>', '>', '<', 22 /*'/'*/'>', '>', '>', '>', '<', '>', '>', '<', 23 /*'('*/'<', '<', '<', '<', '<', '=', ' ', '<', 24 /*')'*/'>', '>', '>', '>', ' ', '>', '>', '>', 25 /*'#'*/'<', '<', '<', '<', '<', ' ', '=', '<', 26 /*'^'*/'>', '>', '>', '>', '<', '>', '>', '>' 27 }; 28 typedef struct StackChar 29 { 30 char c; 31 struct StackChar *next; 32 }SC; //StackChar类型的结点SC 33 typedef struct StackFloat 34 { 35 float f; 36 struct StackFloat *next; 37 }SF; //StackFloat类型的结点SF 38 39 SC *Push(SC *s, char c) //SC类型的指针Push,返回p 40 { 41 SC *p = (SC*)malloc(sizeof(SC)); 42 p->c = c; 43 p->next = s; 44 return p; 45 } 46 SF *Push(SF *s, float f) //SF类型的指针Push,返回p 47 { 48 SF *p = (SF*)malloc(sizeof(SF)); 49 p->f = f; 50 p->next = s; 51 return p; 52 } 53 SC *Pop(SC *s) //SC类型的指针Pop 54 { 55 SC *q = s; 56 s = s->next; 57 free(q); 58 return s; 59 } 60 SF *Pop(SF *s) //SF类型的指针Pop 61 { 62 SF *q = s; 63 s = s->next; 64 free(q); 65 return s; 66 } 67 68 69 float Operate(float a, unsigned char theta, float b) //计算函数Operate 70 { 71 switch (theta) 72 { 73 case '+': return a + b; 74 case '-': return a - b; 75 case '*': return a*b; 76 case '/': return a / b; 77 case '^': return pow(a, b); 78 default: return 0; 79 } 80 } 81 82 char OPSET[OPSETSIZE] = { '+', '-', '*', '/', '(', ')', '#', '^' }; 83 Status In(char Test, char *TestOp) 84 { 85 int Find = false; 86 for (int i = 0; i < OPSETSIZE; i++) 87 { 88 if (Test == TestOp[i]) 89 Find = true; 90 } 91 return Find; 92 } 93 94 Status ReturnOpOrd(char op, char *TestOp) 95 { 96 for (int i = 0; i < OPSETSIZE; i++) 97 { 98 if (op == TestOp[i]) 99 return i; 100 } 101 } 102 103 char precede(char Aop, char Bop) 104 { 105 return Prior[ReturnOpOrd(Aop, OPSET)][ReturnOpOrd(Bop, OPSET)]; 106 } 107 108 109 //计算运算式数值:EvaluateExpression 110 //------------------------------------------------------------- 111 float EvaluateExpression(char* MyExpression) 112 { 113 // 算术表达式求值的算符优先算法 114 // 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合 115 SC *OPTR = NULL; // 运算符栈,字符元素 116 SF *OPND = NULL; // 运算数栈,实数元素 117 char TempData[20]; 118 float Data, a, b; 119 char theta, *c, Dr[] = { '#', '\0' }; 120 OPTR = Push(OPTR, '#'); 121 c = strcat(MyExpression, Dr); 122 strcpy(TempData, "\0");//字符串拷贝函数 123 while (*c != '#' || OPTR->c != '#') 124 { 125 if (!In(*c, OPSET)) 126 { 127 Dr[0] = *c; 128 strcat(TempData, Dr); //字符串连接函数 129 c++; 130 if (In(*c, OPSET)) 131 { 132 Data = atof(TempData); //字符串转换函数(double) 133 OPND = Push(OPND, Data); 134 strcpy(TempData, "\0"); 135 } 136 } 137 else // 不是运算符则进栈 138 { 139 switch (precede(OPTR->c, *c)) 140 { 141 case '<': // 栈顶元素优先级低 142 OPTR = Push(OPTR, *c); 143 c++; 144 break; 145 case '=': // 脱括号并接收下一字符 146 OPTR = Pop(OPTR); 147 c++; 148 break; 149 case '>': // 退栈并将运算结果入栈 150 theta = OPTR->c; OPTR = Pop(OPTR); 151 b = OPND->f; OPND = Pop(OPND); 152 a = OPND->f; OPND = Pop(OPND); 153 OPND = Push(OPND, Operate(a, theta, b)); 154 break; 155 } //switch 156 } 157 } //while 158 return OPND->f; 159 } 160 //符号函数 161 //------------------------------------------------------------- 162 string fuhao(int chu) 163 { 164 string fu; 165 int num_3; 166 if (chu == 1) 167 { 168 num_3 = (rand() % 100) % 4; 169 if (num_3 == 0) fu = '+'; 170 else if (num_3 == 1) fu = '-'; 171 else if (num_3 == 2) fu = '*'; 172 else fu = '/'; 173 return fu; 174 } 175 else 176 { 177 num_3 = (rand() % 20) % 2; 178 if (num_3 == 0) fu = '+'; 179 else fu = '-'; 180 return fu; 181 } 182 } 183 //分数函数 184 //------------------------------------------------------------- 185 string fenshu() 186 { 187 int a1 = 0, b1 = 0, a2 = 0, b2 = 0; 188 a1 = (rand() % (97)); 189 b1 = (rand() % (100 - a1)) + a1 + 1; 190 a2 = (rand() % (97)); 191 b2 = (rand() % (100 - a2)) + a2 + 1; 192 string first_a1, second_b1; 193 string first_a2, second_b2; 194 first_a1 = to_string(a1); 195 second_b1 = to_string(b1); 196 first_a2 = to_string(a2); 197 second_b2 = to_string(b2); 198 string all1 = ""; 199 //随机产生四则运算符 200 int fu = 0; 201 fu = (rand() % 100) % 2; 202 if (fu == 0) 203 { 204 all1 = "(" + first_a1 + "/" + second_b1 + ")" + "+" + "(" + first_a2 + "/" + second_b2 + ")" + "="; 205 } 206 else if (fu == 1) 207 { 208 all1 = "(" + first_a1 + "/" + second_b1 + ")" + "-" + "(" + first_a2 + "/" + second_b2 + ")" + "="; 209 } 210 else if (fu == 2) 211 { 212 all1 = "(" + first_a1 + "/" + second_b1 + ")" + "*" + "(" + first_a2 + "/" + second_b2 + ")" + "="; 213 } 214 else 215 { 216 all1 = "(" + first_a1 + "/" + second_b1 + ")" + "/" + "(" + first_a2 + "/" + second_b2 + ")" + "="; 217 } 218 return all1; 219 } 220 //运算函数 221 //------------------------------------------------------------- 222 string yunsuan(int chu, int kuohao, int range) 223 { 224 int num_1, num_2; 225 int geshu; 226 string str_first, str_second; 227 string all = ""; 228 int ch1; 229 geshu = (rand() % (8) + 2); 230 ofstream fout; 231 for (int i = 1; i <= geshu; i++) 232 { 233 num_1 = (rand() % (range)) + 1; 234 str_first = to_string(num_1); 235 num_2 = (rand() % (range)) + 1; 236 str_second = to_string(num_2); 237 if (kuohao == 1) 238 { 239 ch1 = (rand() % (4)) + 1; 240 switch (ch1){ 241 case 1: 242 { 243 if (all == "") { all = str_first + fuhao(chu) + str_second; } 244 else { all = str_first + fuhao(chu) + all; } 245 }break; 246 case 2: 247 { 248 if (all == "") { all = str_second + fuhao(chu) + str_first; } 249 else { all = all + fuhao(chu) + str_first; } 250 }break; 251 case 3: 252 { 253 if (all == "") { all = "(" + str_first + fuhao(chu) + str_second + ")"; } 254 else { all = "(" + str_first + fuhao(chu) + all + ")"; } 255 }break; 256 case 4: 257 { 258 if (all == ""){ all = "(" + str_second + fuhao(chu) + str_first + ")"; } 259 else { all = "(" + all + fuhao(chu) + str_first + ")"; } 260 }break; 261 } 262 } 263 else 264 { 265 ch1 = (rand() % (2)) + 1; 266 switch (ch1){ 267 case 1: 268 { 269 if (all == "") { all = str_first + fuhao(chu) + str_second; } 270 else { all = str_first + fuhao(chu) + all; } 271 }break; 272 case 2: 273 { 274 if (all == "") { all = str_second + fuhao(chu) + str_first; } 275 else { all = all + fuhao(chu) + str_first; } 276 }break; 277 } 278 } 279 } 280 string c = all.substr(0, 1); 281 string b = all.substr(all.length() - 1, all.length()); 282 if (c == "("&&b == ")") 283 { 284 all = all.substr(1, all.length() - 2); 285 return all + "="; 286 } 287 else 288 { 289 return all + "="; 290 } 291 } 292 293 294 //主函数 295 //------------------------------------------------------------- 296 int main(void) 297 { 298 srand(time(NULL)); 299 int chu, kuohao, range; 300 int calculate_fenshu = 0;//统计分数个数 301 int Y_N; 302 int count;//设置循环次数 303 int disport; 304 ofstream file; 305 ofstream file_result; 306 FILE *f1; 307 cout << "有无除法:(1:有,2:无)" << endl; 308 cin >> chu; 309 cout << "是否有括号:(1:有,2:无)" << endl; 310 cin >> kuohao; 311 cout << "请输入数值的范围:" << endl; 312 cout << "1-"; 313 cin >> range; 314 cout << "请输入一共有多少个算式:" << endl; 315 cin >> count; 316 //分数 317 cout << "是否产生分数(产生真分数):(1:是,2:否)" << endl; 318 cin >> Y_N; 319 file.open("test.txt"); 320 //************将生成的算式保存在文件中********************** 321 if (Y_N == 1) 322 { 323 cout << "产生的" << count << "个算式中,希望有几个分数式:" << endl; 324 cout << "分数式结果请保留两位小数:" << endl; 325 cin >> calculate_fenshu; 326 for (int m = 0; m < calculate_fenshu; m++) 327 { 328 file << fenshu() << endl; 329 } 330 } 331 332 for (int i = calculate_fenshu; i <= count; i++) 333 { 334 file << yunsuan(chu, kuohao, range) << endl; 335 //fenshu(); 336 } 337 file.close(); 338 //************************* 339 char a[255]; 340 double cin_result; 341 int jishu = 0; 342 cout << "是否将生成的算式以及结果输出到文件:(1:是, 2:否)" << endl; 343 cin >> disport; 344 cout << "生成的四则运算式为:" << endl; 345 cout << endl; 346 if (disport == 1) 347 { 348 file_result.open("rusult.txt"); 349 file_result << "***************************四则运算式****************************" << endl; 350 if (f1 = fopen("test.txt", "r")) 351 { 352 for (int j = 0; j < count; j++) 353 { 354 fscanf(f1, "%s", a); //文件内容一行不要大于255个字符 355 356 cout << j + 1 << "."; 357 cout << a << endl; 358 file_result << j + 1 << "." << a << endl; 359 cout << "请输入结果:" << endl; 360 file_result << "请输入结果:" << endl; 361 cin >> cin_result; 362 file_result << cin_result; 363 file_result << endl; 364 if (fabs(cin_result - EvaluateExpression(a)) < 1e-2) 365 { 366 cout << "结果正确" << endl; 367 file_result << "结果正确" << endl; 368 jishu = jishu + 1; 369 } 370 else 371 { 372 cout << "结果错误,正确答案为:" << EvaluateExpression(a) << endl; 373 file_result << "结果错误,正确答案为:" << EvaluateExpression(a) << endl; 374 } 375 } 376 cout << "您一共答对" << jishu << "道题,答错" << count - jishu << "道题。" << endl; 377 file_result << "您一共答对" << jishu << "道题,答错" << count - jishu << "道题。" << endl; 378 fclose(f1); 379 } 380 file.close(); 381 } 382 else 383 { 384 385 if (f1 = fopen("test.txt", "r")) 386 { 387 for (int j = 0; j < count; j++) 388 { 389 fscanf(f1, "%s", a); //文件内容一行不要大于255个字符 390 cout << j + 1 << "."; 391 cout << a << endl; 392 cout << "请输入结果:" << endl; 393 cin >> cin_result; 394 if (fabs(cin_result - EvaluateExpression(a)) < 1e-2) 395 { 396 cout << "结果正确" << endl; 397 jishu = jishu + 1; 398 } 399 else 400 { 401 cout << "结果错误,正确答案为:" << EvaluateExpression(a) << endl; 402 } 403 } 404 cout << "您一共答对" << jishu << "道题,答错" << count - jishu << "道题。" << endl; 405 fclose(f1); 406 } 407 file.close(); 408 } 409 system("DEL /f test.txt"); 410 return 0; 411 }
程序运行结果如图:
对于四则运算题目要求的选择如下:
按照此要求,产生如下四则运算式,并计算:
由此,得出答题统计情况如下:
同时,输出到文件中的结果如下:
再次运行结果如下:
输出到文本为:
本次结对开发的项目开发总结如下:
<
项目计划 总 结: | |||||
日期\任务 | 听课 | 编写程序 | 查阅资料 | 日总计 | |
星期一 | 2 | 1 | 1 | 4 | |
星期二 | 2 | 1 | 3 | ||
星期三 | 2 | 1 | 3 | ||
星期四 | 2 | 2 | 1 | 5 | |
星期五 | 5 | 1 | 6 | ||
星期六 | |||||
星期日 | |||||
周总计 | 4 | 12 | 5 | 21 |
<
时间记录日志: | ||||||
日期 | 开始时间 | 结束时间 | 中断时间 | 静时间 | 活动 | 备注 |
3月14日 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程 |
19:30 | 21:50 | 10 | 180 | 编写程序 | 编写程序架构、增加新功能&查资料 | |
3月15日 | 18:20 | 21:45 | 25 | 135 | 编写程序 | |
3月16日 | 14:30 | 17:40 | 10 | 180 | 查阅资料 | 学习数据结构相关知识 |
编写程序 | ||||||
3月17日 | 14:00 | 15:50 | 10 | 100 | 听课 | 软件工程 |
18:20 | 21:20 | 180 | 编写程序 | 调试程序寻找错误地方 | ||
3月18日 | 14:10 | 20:40 | 90 | 300 | 编写程序 | 调试程序为主,并修改部分功能,规范代码 |
21:00 | 22:00 | 60 | 看书 | |||
3月19日 | 8:00 | 9:00 | 60 | 调试 | 最终调试 |
<
缺陷记录日志: | ||||
日期 | 编号 | 引入阶段 | 排除阶段 | 修复时间&问题描述 |
3月14日 | 1 | 编码 | 编译 | 1.5小时,计算函数的数据结构出错 |
3月15日 | 2 | 编码 | 编码 | 1小时,产生的随机算式输出到文本中,并进行读取时出错。 |
3月16日 | 3 | 编码 | 编译 | 1.5小时,用计算函数调试产生的文本中的算式,不能正确计算出结果 |
3月17日 | 4 | 编码 | 编译 | 2小时,分数式无法正确判断结果 |
3月18日 | 5 | 编码 | 编译 | 3.5小时,保存文件时,无法将答题结果输入到文件中;部分代码不规范 |
3月19日 | 6 | 编码 | 编译 |