软件工程Ⅱ:小学四则运算

作业要求来源于 https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2186

我的GitHub远端库 https://github.com/WAN-Y/gggit

一、题目要求:

像《构建之法》的人物阿超那样,写一个能自动生成小学四则运算题目的命令行 “软件”。


具体要求:任何编程语言都可以,命令行程序接受一个数字输入,然后输出相应数目的四则运算题目和答案。例如输入数字是 30, 那就输出 30 道题目和答案。 运算式子必须至少有两个运算符,运算数字是在 100 之内的正整数,答案不能是负数。 如:

23 - 3 * 4 = 11

扩展要求:

1) 要求能出和真分数 (二分之一, 十二分之五,等)相关的练习题。

2) 并且要求能处理用户的输入,并判断对错,打分统计。 要求能处理用户输入的真分数, 如 1/2, 5/12 等。

初步拟定要实现的功能后,估计一下自己需要花多长时间。编程过程中记录自己实际用了多长时间。

然后和同学们比较一下各自程序的功能、实现方法的异同等等。

写博客纪录自己实现的过程和思路。

 

二、个人软件过程耗时估计与统计表

PSP2.1 Personal Software Process Stages Time Senior Student Time
Planning 计划 0.5 0.5
· Estimate 估计这个任务需要多少时间 6  7
Development 开发 6  
· Analysis 需求分析 (包括学习新技术) 0.5 0.5
· Design Spec 生成设计文档 0 0.2
· Design Review 设计复审 0 0.1
· Coding Standard 代码规范 0.2  
· Design 具体设计 2 1
· Coding 具体编码 2 3
· Code Review 代码复审 0.5 1
· Test 测试(自我测试,修改代码,提交修改) 0.5 0.5
Reporting 报告 0 3
· 测试报告 0  
· 计算工作量 0  
· 并提出过程改进计划 0

 

三、代码提交

实现过程和思路

我选择了c语言来编写这次的程序。

1.先写出获取题目数量的语句,并用for()循环体输出题目序号。(此后每输出一个序号就随机一个等式。)

 

    printf("请输入题目数量:");
    scanf("%d",&num);
    for(i=1;i<=num;i++)
    {
        printf("%d.\n",i);
    }

 

2.随机等式的“部件”。为运算数和运算符建立新变量,并获取循环数。

(运算符是通过随机获得0~3的数字,再用switch()语句分别对应+-×÷得出的。)

 

    srand((int)time(0));
    a=rand()%100;
    b=rand()%100;
    c=rand()%100;
    m=rand()%4;
    n=rand()%4;
  
  switch(m)
    {
    case 0:
            x='+';
            break;
    case 1:
            x='-';
            break;
    case 2:
            x='*';
            break;
    case 3:
            x='/';
            if(b==0)
                b=rand()%100; //避免除数为零
            break;
        }

3.计算等式结果

 

         switch(x) //从左到右算起
         {
         case '*':
             v=a*b;  //v变量存储第一次运算结果
             break;
         case '/':
             v=(float)a/b;
             break;
         case '+':
             if(y!='*'&&y!='/') //需要先算后面部分时跳过
             {v=a+b;}
             break;
         case '-':
             if(y!='*'&&y!='/') //需要先算后面部分时跳过
             {v=a-b;}
             break;
         }
        switch(y) //计算右半部分
        {
        case '+':
            w=v+c; //w存储最终结果
            break;
        case '-':
            w=v-c;
            break;
        case '*':
            if(x=='+') //1.从右往左算回去
            {w=a+(b*c);}
            else if(x=='-')
            {w=a-(b*c);}
            else
            {w=v*c;}//2.顺序计算
            break;
        case '/':
            if(x=='+')//1.从右往左算回去
            {w=a+((float)b/c);}
            else if(x=='-')
            {w=a-((float)b/c);}
            else
            {w=v/c;}//2.顺序计算
        }

 

  4.若计算结果为负,重新执行循环体。

        if(w<0)
        {
            goto loop;
        }

  5.输出等式及结果。

    for(i=1;i<=num;i++)
    {
        printf("%d.\n",i);
        printf("%d %c %d %c %d = ",formula[i][0],formula[i][1],formula[i][2],formula[i][3],formula[i][4]);
        printf("%.2f\n",result[i]);
    }

6.程序运行结果

 

 

感想和体会

1.这次写代码的过程依旧犯了些基础错误,像是输出变量的时候加上了&取地址符,switch()里没有写break语句等等。

 

2.我发现:程序的主要功能写起来所花的时间是比较少的。在此次编码的过程里,耗时最长的居然是避免结果为负数这一附加要求。

虽然上面的代码里只有简单的一个go to语句,但实际上我思考所消耗的时间和写其他所有代码的时间是差不多的。

这是因为我的逻辑思考收到了比较大的考验。

什么时候结果会为负数?只有减法。

想把第一次和第二次的运算结果分开检验,那么有减号的情况有多少种呢?

非顺序的运算要怎么照顾到呢?用什么语句比较好?……

在思考的过程里大脑甚至当机了好一会儿,辛苦写出来的代码还总是运行失败,最后还是改成go to。

 

事先想好框架并构思好大致逻辑比闷头写要顺畅得多——也是我在此次作业中的一个小感想。

寻找可能会出bug的地方并尝试检验实在是很耗心力……

不难想象功能更复杂的软件要遇到多少更头大的问题,我想这就是软件工程之难的一个小缩影吧。

 

posted on 2018-10-15 13:28  WAN*Y  阅读(201)  评论(1编辑  收藏  举报

导航