结组项目-四则运算3
團隊成員:苗堃(http://www.cnblogs.com/brucekun/p/5294368.html)、羅毅(http://www.cnblogs.com/ly199553/p/5294779.html)?
PSP總結http://www.cnblogs.com/ly199553/p/5295545.html
? ? 本次軟件工程老師提出了新任務:在上一次四則運算的題目基礎上增加新的功能:比如四則運算要求能求出運算結果,對于用戶輸入的運算結果進行比對結果是否正確,加入真分數的計算,判斷是否四則運算的產生式是否重復等。但這次要求我們結組開發,而且結組的目的是:兩人合作,分解任務,協同開發,仔細分析程序的過程,同時在開發過程中需要檢查程序的各個流程,有問題需要共同討論解決。
? ? 之后我便明確了我的任務:將上一次的程序產生的計算式全部考慮成string串,我做的就是一個接口,進入我的接口傳入string類型的字符串后就能出棧得到需要的答案。這樣我的任務便十分明確了,我希望在這次任務中用上我學的棧和隊列的知識。前期我們商量后決定使用另一個小伙伴的程序作為模版進行迭代開發,所以我花了一個晚上研究了他寫的程序,大致清晰了流程后,我考慮使用容器來簡化整個計算的過程。參考了網上的一些小神的代碼后,我開始如下編程設計:
? ? 使用五個容器類deque<char>?coll0? deque<char>?coll1;?stack<char>?coll2;?deque<char>?coll3; stack<double>coll4; 整體過程就是通過coll0來消除string式中的空格,coll1來記錄產生的中綴表達式,coll2來記錄運算符,因為運算符有彼此的優先級和消除括號等,再通過coll3和coll4就將轉換的后綴表達式可以計算出結果。將其中設計的過程全部設計為函數,以便以后可以封裝成類可以調用。主要的問題就是處理多位數時判斷花了一些功夫寫在另一篇博客上了,具體詳http://www.cnblogs.com/ly199553/p/5292391.html,本次程序先研討了小學2-6年級的數學水平,發現真分數計算才是重點,乘除法不應過于復雜,而且最好有面向兒童的界面。
下面是整個代碼:
1 #include<stack> 2 #include<iostream> 3 #include<deque> 4 #include<string> 5 #include<sstream> 6 #include<time.h> 7 using namespace std; 8 9 int Num[100]; //將數字存入數組a 10 string op_arrays[100]; //將運算符存入數組b 11 string All[100]; //合成總數組e 12 string fu[100]; //輔助數組 13 int true_num = 0; //統計做對的題目數 14 int false_num = 0; //統計做錯的題目數 15 16 bool isPra(char); //判斷是否為括號 17 int getPri(char); //獲得符號優先性 18 void check(char c, stack<char>& coll2, deque<char>& coll3);//判斷符號優先性 19 void allocate(deque<char>& coll1, stack<char>& coll2, deque<char>& coll3); //將中綴表達式分解為符號和運算數 20 void calculate(deque<char>& coll3, stack<double>& coll4); //計算后綴表達式 21 22 int main() 23 { 24 srand((int)time(NULL));//設置隨機種子,使得程序每次運行的結果都不同 25 int subject_number; //出題數量 26 int random_number = 0; //運算數字字數 27 int operation_character = 0; 28 int fuhao = 0; //判定運算符 29 30 int Jude_has_brackets; //定義左、右括號的是否存在的隨機變量 31 string left; //左括號變量 32 string right; //左括號變量 33 string sign = "a"; //定義符號變量 34 char Jude_has_mul_dev; //定義是否需要乘除法的變量 35 36 deque<char> coll0; //消除中綴表達式的空格 37 deque<char> coll1; //盛放中綴表達式 38 stack<char> coll2; //盛放操作符 39 deque<char> coll3; //盛放后綴表達式 40 stack<double>coll4; //計算后綴表達式的輔助容器 41 42 int min, Max; //定義輸入的值得范圍的最值(僅能輸入整數<=30) 43 string w = " "; 44 45 //寫一個簡易菜單 46 cout << "歡 / ̄\_/ ̄\ "<<endl; 47 cout << "迎 ▏ ▔▔▔▔\ " << endl; 48 cout << "使 /\ / ﹨" << endl; 49 cout << "用 ∕ / )" << endl; 50 cout << "小 ▏ ● ▏"<<endl; 51 cout << "天 ▏ ▔█ " << endl; 52 cout << "才 ◢██◣ /\__/" << endl; 53 cout << "四 █████◣ /" << endl; 54 cout << "則 █████████████◣ " << endl; 55 cout << "運◢██████████████▆▄" << endl; 56 cout << "算 █◤◢██◣◥█████████◤\" << endl; 57 cout << "自◥◢████ ████████◤ \" << endl; 58 cout << "助 █████ ██████◤ ﹨" << endl; 59 cout << "系 │ │█████◤ ▏" << endl; 60 cout << "統 │ │ ▏" << endl; 61 cout << " ∕ ∕ /▔▔▔\ ∕" << endl; 62 cout << " ∕___/﹨ ∕ \ /\" << endl; 63 cout << " \ \_ ﹨/ ﹨" << endl; 64 cout << " \___\ ﹨/▔\﹨/▔\" << endl; 65 cout << " \ ∕" << endl; 66 cout << "1.請輸入產生數字的范圍(最小和最大):"; 67 cin >> min >> Max; 68 cout << "提示:若您需要做乘除法 請不要做超過30以外的乘除法" << endl; 69 cout << endl; 70 cout << "2.是否需要乘除法[y為需要乘除法 n為不需要乘除法] "; 71 cin >> Jude_has_mul_dev; 72 while (min<0) 73 { 74 cout << "請做正數運算:" << endl; 75 cout << "輸入最小值" << endl; 76 cin >> min; 77 } 78 while (Max>30 && Jude_has_mul_dev == 'y') 79 { 80 cout << "請重新輸入最大值:" << endl; 81 cin >> Max; 82 } 83 cout << "請輸入出題數量:"; 84 cin >> subject_number; 85 86 int i = 0, j, k; 87 if ('y' == Jude_has_mul_dev) 88 { 89 random_number = rand() % 9 + 2; //隨機生成2~10個數 90 for (j = 0; j < subject_number; j++) //設置題目數量 91 { 92 //清除數組元素 93 memset(Num, 0, sizeof(Num)); 94 memset(op_arrays, 0, sizeof(op_arrays)); 95 memset(fu, 0, sizeof(fu)); 96 97 random_number = rand() % 9 + 2; //隨機生成2~10個數 98 for (i = 0; i < random_number; i++) 99 { 100 stringstream ss; 101 operation_character = rand() % (Max - min + 1) + min; 102 Num[i] = operation_character; 103 fuhao = rand() % 4 + 1; 104 switch (fuhao) 105 { 106 case 1:sign = "+"; break; 107 case 2:sign = "-"; break; 108 case 3:sign = "*"; break; 109 case 4:sign = "/"; break; 110 } 111 //若為除法則除數不為零 112 while (Num[i] == 0 && i >= 1) 113 { 114 if (op_arrays[i - 1] == "/") 115 { 116 operation_character = rand() % (Max - min + 1) + min; 117 Num[i] = operation_character; 118 } 119 } 120 op_arrays[i] = sign; 121 122 fu[4 * i] = w; 123 ss << Num[i]; 124 ss >> fu[4 * i + 1]; 125 fu[4 * i + 2] = w; 126 if (i != (random_number - 1)) //最后一次不產生符號 127 fu[4 * i + 3] = op_arrays[i]; 128 else fu[4 * i + 3] = w; 129 } 130 Jude_has_brackets = rand() % 2 + 1; //隨機確定有無括號 131 switch (Jude_has_brackets) 132 { 133 case 1: 134 left = "("; 135 right = ")"; 136 break; 137 case 2: 138 left = w; 139 right = w; 140 break; 141 } 142 143 for (i = 0; i < random_number; i++) 144 { 145 for (k = 0; k < (random_number - 1) / 2; k++) 146 { 147 fu[4 * k] = left; 148 if (left == "(") 149 { 150 fu[4 * k + 10] = right; 151 } 152 } 153 if ((fu[4 * i] == left) && (fu[4 * i + 2] == right)) 154 { 155 fu[4 * i] = w; 156 fu[4 * i + 2] = w; 157 } 158 159 All[j] += fu[4 * i] + fu[4 * i + 1] + fu[4 * i + 2] + fu[4 * i + 3]; 160 } 161 cout << j + 1 << "題. " << All[j] << "= " ; 162 for (int i = 0; i != All[j].size(); ++i) 163 { 164 //逐一加入每個字符,這里使用deque因為deque在兩端刪除添加的速度最快 165 coll0.push_back(All[j][i]); //在尾部加入一個元素 166 } 167 168 //將coll0轉換為后綴表達式coll1 169 for (int i = 0; i != All[j].size(); ++i) 170 { 171 char k = coll0.front(); 172 coll0.pop_front(); 173 if (k != ' ') //消除空格 174 coll1.push_back(k); 175 } 176 //從coll中取出元素,分配元素到coll2和coll3中 177 allocate(coll1, coll2, coll3); 178 179 //計算后綴表達式 180 calculate(coll3, coll4); 181 182 double result = 0; 183 cin >> result; 184 if (result == coll4.top()) 185 { 186 cout << "正確!" << endl; 187 true_num++; 188 cout << "計算結果為:" << coll4.top() << endl; 189 } 190 else 191 { 192 cout << "錯誤!" << endl; 193 false_num++; 194 cout << "計算結果為:" << coll4.top() << endl; 195 } 196 //將棧清空 197 coll4.pop(); 198 } 199 if (true_num >= false_num) 200 cout << "恭喜你!您共做對" << true_num << "道題!" << "做錯" << false_num << "道題!" << endl; 201 else 202 cout << "還需加油!您共做對" << true_num << "道題!" << "做錯" << false_num << "道題!" << endl; 203 } 204 else 205 { 206 random_number = rand() % 9 + 2; //隨機生成2~10個數 207 for (j = 0; j < subject_number; j++) //設置題目數量 208 { 209 //清除數組元素 210 memset(Num, 0, sizeof(Num)); 211 memset(op_arrays, 0, sizeof(op_arrays)); 212 memset(fu, 0, sizeof(fu)); 213 214 random_number = rand() % 9 + 2; //隨機生成2~10個數 215 for (i = 0; i < random_number; i++) 216 { 217 stringstream ss; 218 operation_character = rand() % (Max - min + 1) + min; 219 Num[i] = operation_character; 220 fuhao = rand() % 2 + 1; 221 switch (fuhao) 222 { 223 case 1:sign = "+"; break; 224 case 2:sign = "-"; break; 225 } 226 op_arrays[i] = sign; 227 228 fu[4 * i] = w; 229 ss << Num[i]; 230 ss >> fu[4 * i + 1]; 231 fu[4 * i + 2] = w; 232 if (i != (random_number - 1)) //最后一次不產生符號 233 fu[4 * i + 3] = op_arrays[i]; 234 else fu[4 * i + 3] = w; 235 } 236 Jude_has_brackets = rand() % 2 + 1; //隨機確定有無括號 237 switch (Jude_has_brackets) 238 { 239 case 1: 240 left = "("; 241 right = ")"; 242 break; 243 case 2: 244 left = w; 245 right = w; 246 break; 247 } 248 249 for (i = 0; i < random_number; i++) 250 { 251 for (k = 0; k < (random_number - 1) / 2; k++) 252 { 253 fu[4 * k] = left; 254 if (left == "(") 255 { 256 fu[4 * k + 10] = right; 257 } 258 } 259 if ((fu[4 * i] == left) && (fu[4 * i + 2] == right)) 260 { 261 fu[4 * i] = w; 262 fu[4 * i + 2] = w; 263 } 264 265 All[j] += fu[4 * i] + fu[4 * i + 1] + fu[4 * i + 2] + fu[4 * i + 3]; 266 } 267 cout << j + 1 << "題. " << All[j] << "= " << endl; 268 for (int i = 0; i != All[j].size(); ++i) 269 { 270 //逐一加入每個字符,這里使用deque因為deque在兩端刪除添加的速度最快 271 coll0.push_back(All[j][i]); //在尾部加入一個元素 272 } 273 274 //將coll0轉換為后綴表達式coll1 275 for (int i = 0; i != All[j].size(); ++i) 276 { 277 char k = coll0.front(); 278 coll0.pop_front(); 279 if (k != ' ') //消除空格 280 coll1.push_back(k); 281 } 282 //從coll中取出元素,分配元素到coll2和coll3中 283 allocate(coll1, coll2, coll3); 284 285 //計算后綴表達式 286 calculate(coll3, coll4); 287 288 double result = 0; 289 cin >> result; 290 if (result == coll4.top()) 291 { 292 cout << "正確!" << endl; 293 true_num++; 294 cout << "計算結果為:" << coll4.top() << endl; 295 } 296 else 297 { 298 cout << "錯誤!" << endl; 299 false_num++; 300 cout << "計算結果為:" << coll4.top() << endl; 301 } 302 //將棧清空 303 coll4.pop(); 304 } 305 if (true_num >= false_num) 306 cout << "恭喜你!您共做對" << true_num << "道題!" << "做錯" << false_num << "道題!" << endl; 307 else 308 cout << "還需加油!您共做對" << true_num << "道題!" << "做錯" << false_num << "道題!" << endl; 309 } 310 return 0; 311 } 312 313 314 //判斷是否為括號 315 bool isPra(char c) 316 { 317 if (c == '(' || c == ')') 318 return true; 319 else 320 return false; 321 } 322 323 //獲得符號的優先性 324 int getPri(char c) 325 { 326 switch (c) 327 { 328 case '+': 329 case '-': 330 return 0; //如果是加減,返回0 331 break; 332 case '*': 333 case '/': 334 return 1; //如果是乘除,返回1 335 break; 336 case '(': 337 case ')': 338 return -1; //注意,這里將括號設為最低優先級,因此括號不會被彈出,除非遇到右括號 339 break; 340 } 341 return 2; 342 } 343 344 //判斷符號的優先性 345 void check(char c, stack<char>& coll2, deque<char>& coll3) 346 { 347 if (coll2.empty()) 348 { 349 coll2.push(c); 350 return; 351 } 352 353 if (isPra(c)) 354 { 355 if (c == '(') 356 coll2.push(c); 357 else 358 { 359 //彈出所有元素直到遇到左括號 360 while (coll2.top() != '(') 361 { 362 char ch = coll2.top(); 363 coll3.push_back(ch); 364 coll2.pop(); 365 } 366 367 //當遇到左括號時,彈出但不加入coll3(后綴表達式中)--(“(”“)”都不放入后綴表達式中) 368 coll2.pop(); //彈出左括號 369 } 370 } 371 else //如果不是括號 372 { 373 //取出棧頂元素,與當前符號進行優先性比較 374 char sym = coll2.top(); 375 376 //比較兩符號的優先性 377 if (getPri(c) <= getPri(sym)) 378 { 379 //如果c的優先性比棧頂符號小或等于,彈出棧頂元素 380 coll2.pop(); 381 //并將其壓入coll3(后綴表達式)中 382 coll3.push_back(sym); 383 //遞歸調用check,比較當前符號c與下一個棧頂符號的優先性 384 check(c, coll2, coll3); 385 } 386 else 387 { 388 //如果c比棧頂符號優先級大,那將c壓入coll2(操作符棧)中 389 coll2.push(c); 390 } 391 } 392 } 393 394 //從coll中取出元素,分配元素到coll2和coll3中 395 void allocate(deque<char>& coll1, stack<char>& coll2, deque<char>& coll3) 396 { 397 while (!coll1.empty()) 398 { 399 char c = coll1.front(); 400 coll1.pop_front(); 401 402 if (c >= '0'&&c <= '9') 403 { 404 coll3.push_back(c); 405 //判斷是否為兩位數 406 if (!coll1.empty()) 407 { 408 c = coll1.front(); 409 if (c >= '0'&&c <= '9') 410 coll3.push_back('@'); 411 } 412 } 413 else 414 { 415 //調用check函數,針對不同情況作出不同操作 416 check(c, coll2, coll3); 417 } 418 419 } 420 421 //如果輸入結束,將coll2的元素全部彈出,加入后綴表達式中 422 while (!coll2.empty()) 423 { 424 char c = coll2.top(); 425 coll3.push_back(c); 426 coll2.pop(); 427 } 428 } 429 430 431 //計算后綴表達式(修改) 432 void calculate(deque<char>& coll3, stack<double>& coll4) 433 { 434 while (!coll3.empty()) 435 { 436 char c = coll3.front(); //取出第一個元素 437 double op = 0; 438 coll3.pop_front(); //并彈出此元素 439 //coll3.erase(coll3.begin()); 440 //如果是操作數,壓入棧中 441 442 //若是兩位數在壓入輔助數組后需要進行判斷 443 if (c >= '0'&&c <= '9') 444 { 445 op = (c - '0'); 446 coll4.push(op); 447 //cout<<"op="<<op<<endl; 448 } 449 else if (c == '@') //如果是兩位數則再讀一位(若超過兩位需要while擴展) 450 { 451 char d = coll3.front(); 452 op = coll4.top(); 453 coll4.pop(); 454 op = op * 10 + (d - '0'); 455 coll4.push(op); 456 coll3.pop_front(); 457 } 458 else //如果是操作符,從棧中彈出元素進行計算 459 { 460 double op1 = coll4.top(); 461 coll4.pop(); 462 double op2 = coll4.top(); 463 coll4.pop(); 464 switch (c) 465 { 466 case '+': 467 coll4.push(op2 + op1); 468 break; 469 case '-': 470 coll4.push(op2 - op1); 471 break; 472 case '*': 473 coll4.push(op2*op1); 474 break; 475 case '/': 476 coll4.push(op2 / op1); //注意是op2(op)op1而不是op1(op)op2 477 break; 478 } 479 } 480 } 481 }運行截圖:
工作截圖:
這星期有些懈怠了編程激情有些下降以至于都沒有加上真分數等等的情況,所以我還要反思,因為最終要成為一個系統,我決定在安卓手機上顯示,所以只有開始轉換成java了,希望下次我能圓滿完成把。
轉載于:https://www.cnblogs.com/ly199553/p/5294779.html
總結
以上是生活随笔為你收集整理的结组项目-四则运算3的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 5631 Rikka with
- 下一篇: POJ 3268:Silver Cow