四则运算出题前三项功能全部实现,新增扩展功能:输出“循环小数”。打印带有循环小数答案的题目列表等。不过提交版本为最终要求版本,功能1、2均注释掉予以留存。
要求1 参考《构建之法》第4章两人合作,结对编程上述功能,要求每人发布随笔1篇 (代码是共同完成的,博客是分别完成的)。 (1) 给出每个功能的重点、难点、编程收获。(2)给出结对编程的体会,以及 (3) 至少5项在编码、争论、复审等活动中花费时间较长,给你较大收获的事件。 (10分)
功能一:控制台运行、随机出题20道、判断结果、记录正确题目数量。
重点:随机出题、添加括号、算式组合、计算得数。难点:算式组合、计算得数。成果展示:
因为括号是之后运行的,所以只需要在括号部分进行修改即可消去括号。
编程收获:
有的时候采用简单的方式也可以获得良好的效果。比如括号的添加等问题,必须承认如果变化需求为5个数字的运算,那么我的程序就需要很大改动。但是针对本问题,“写死”括号的所有情况是我想到的比较简单的方法。
CalculateQuestion::CalculateQuestion() { // 生成加括号方式的随机数 0-8 this->brackets = rand() % 9; for (int i = 0; i < 4; i++) { // 生成0-9的随机整数 this->num[i] = rand() % 10; } for (int i = 0; i < 3; i++) { // 生成随机运算符号 + - * / this->character[i] = character_arr[rand() % 4]; } this->express = ""; this->express += (turnBracket(this->brackets, 0) + to_string(this->num[0])); for (int i = 0, j = 1; i < M; i++, j += 2) { this->express += (turnBracket(this->brackets, j) + this->character[i] + turnBracket(this->brackets, j + 1) + to_string(this->num[i])); } this->express += turnBracket(this->brackets, 7); }
功能2:支持括号,小数点输入结果并判断正误。
重点:增加括号,难点:数值计算+小数点表达,结果展示:
说明:本程序支持小数点判断,因为出小数点情况少,所以只展示运行正确、计算正确的截图。本程序还支持针对分数结果的判断,这些功能都被注释掉保存在代码中。
编程收获:在和同学一起编程的同时,可以相互交流一些小技巧,相互之间都有点小的想法和技巧。不一定谁的好,但是有用就可以!
在处理除法除数为0的问题上,我们就用到了很有趣的办法,若除数出现0(不管是数字还是表达式),直接跳出循环,生成到下一题目。这样就跳过了报错环节!
争论:花大量时间学习、做一个扩展性好的程序重要?还是及时完成作业重要?显然是后者,这是工程课,不是编程课。每个人的想法不一样,但是解决问题就好。所以我们的括号生成方法就比较简单。缺少了扩展性。
在此给出算式得出结果的过程,展示代码如下:
string CalculateQuestion::getExpressionAndResult() { string str1 = this->express; // 中缀表达式 string str2 = ""; // 后缀表达式 stack<char> cs; // 字符栈 stackis; // 整数栈 int len = str1.length(); for (int i = 0; i < len; i++){ if (str1[i] >= '0' && str1[i] <= '9') // 如果是整数直接放在后缀表达式中 str2.push_back(str1[i]); else{ if (cs.empty() || str1[i] == '(') // 字符栈为空或当前符号位(直接进符号栈 cs.push(str1[i]); else{ // 判断当前符号与栈顶符号优先级 if (str1[i] == ')'){ // ( 要将最近的)之前的符号都输出 while (cs.top() != '(') { str2.push_back(cs.top()); cs.pop(); } cs.pop(); // 弹出 ( } else{ // 当前元素不是 ( 比较优先级 if (str1[i] == '*' || str1[i] == '/') { while (!cs.empty() && (cs.top() == '*' || cs.top() == '/') && cs.top() != '(') { str2.push_back(cs.top()); cs.pop(); } cs.push(str1[i]); } else { while (!cs.empty() && cs.top() != '(') { str2.push_back(cs.top()); cs.pop(); } cs.push(str1[i]); } } } } } while (!cs.empty()) { str2.push_back(cs.top()); cs.pop(); } // cout << str2 << endl; //由后缀表达式计算结果 Fraction temp1, temp2, temp3; len = str2.length(); for (int i = 0; i < len; i++){ if (str2[i] >= '0' && str2[i] <= '9'){ int t = str2[i] - 48; is.push(Fraction(t, 1)); } else{ // temp1,temp2 为分母为1,分子为is.top()的分数 temp1 = is.top(); is.pop(); temp2 = is.top(); is.pop(); if (str2[i] == '+'){ temp3 = temp2 + temp1; } else if (str2[i] == '-'){ temp3 = temp2 - temp1; } else if (str2[i] == '*'){ temp3 = temp2 * temp1; } else if (str2[i] == '/'){ //return "-1"; if (temp1.numerator == 0) { return "-1"; } temp3 = temp2 / temp1; } is.push(temp3); } } string decimal_string = is.top().decimal(); //功能一和功能二相关代码 //输出值为代分数形式 //string res = this->express + "=#" + is.top().reduct();//用作判断 //输出值为小数形式 //string res = this->express + "=#";//用作判断 //is.top().reduct(); //res += is.top().decimal(); //功能三代码 string res = this->express + "=\t\t" + is.top().reduct() + "\t"; //若添加小数结果相关代码,仅仅需要将下一行注释符号取消 //res += is.top().decimal(); // 必须在 reduct 执行之后(化成带分数)才能进行,不输出小数部分 //测试功能代码 //cout << is.top().decimal() << endl; //cout << decimal_string << endl; //cout << res << endl; if (isSame(decimal_string) == 0){ res = "-1"; } return res; }
不得不说的是,没有及时的补充注释。这个严重违反了我们之前的代码规范。
功能3: 限定题目数量,"精美"打印输出,避免重复
重点:控制台输入命令、精美打印,难点:避免重复,成果展示:
如上图片展示我的程序运行结果:1输出带有分数和小数表示答案的题目并打印(自己扩展功能)2输出仅带有分数答案的题目并写入txt(要求),3测试乱七八糟的命令行输入。
命令行输入测试包括3项内容:1第一个参数不是“-c”,2第2个参数不是“正整数”,3 第三项参数不为空。
编程收获:在解决一个问题时,要考虑多种途径。在解决“避免重复”的问题上,我没有对表达式进行判断,而直接要求其结果不同。若结果不同,则表达式也不会相同。所以只要我对所有结果进行对比,若有相同结果,则此题不输出。按照此思路虽然有点“偷懒”,但是完成了预期目标。
如下展示有关避免重复相关的代码。
int isSame(string result_need_different); template <class T> int getArrayLen(T& array) { return (sizeof(array) / sizeof(array[0])); } string a[10000]; int result[1000]; int sameresult = 0; int isSame(string result_need_different){ int result_number; //cout << "!!!"; //result_number = result.length; int x = getArrayLen(a); for (int i = 1; i < sameresult; i++){ if (result_need_different == a[i]){ return 0; //cout << "结果相同!"; } } a[sameresult++] = result_need_different; return 1; } //在输出表达式函数末尾的判断: if (isSame(decimal_string) == 0){ res = "-1"; }
编程收获:在完成这段代码过程中,有关结果怎么存储这样的基础问题。感觉希望安心下来把所有语法全都仔仔细细传一遍。之后还对怎么找错误进行激烈的争夺电脑活动,都想尝试自己的想法,不希望对方在自己思考的时候碰电脑。
争论:对于debug好用?还是输出结果查看好用?我是喜欢debug,可是队友偏偏喜欢把结果输出查看。。。不管怎么说,我依旧觉得debug,但是有的时候直接输出确实很快的就可以看到结果。
要求2 给出照片1张,包括结对的2位同学、工作地点、计算机,可选项包括其他能表达结对编程工作经历的物品或场景。 (5分)
工作地点是在我的实验室,传媒西楼220,主要使用的是我的台式电脑.
要求3 使用coding.net做版本控制。checkin 前要求清理 临时文件、可执行程序,通常执行 build-clean可以达到效果。(5分)
(已上传)地址:
https://git.coding.net/Rio56/f4.git