2017秋-软件工程第四次作业(3)-四则运算出题

四则运算出题前三项功能全部实现,新增扩展功能:输出“循环小数”。打印带有循环小数答案的题目列表等。不过提交版本为最终要求版本,功能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;        // 字符栈
    stack<Fraction> is;        // 整数栈
    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

 

转载于:https://www.cnblogs.com/-Rio56/p/7650083.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值