• 高级软件工程第二次作业--四则运算生成器


    1 项目 GitHub 地址

            https://github.com/shuangshuanggit

    2 预估耗时与实际耗时

    PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
    Planning 计划 30  60
    · Estimate · 估计这个任务需要多少时间 120  240
    Development 开发 300   780
    · Analysis · 需求分析 (包括学习新技术)   30   40
    · Design Spec · 生成设计文档   0   0
    · Design Review · 设计复审 (和同事审核设计文档)   0   30
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范)   0   0
    · Design · 具体设计   30   60
    · Coding · 具体编码   120  500
    · Code Review · 代码复审   60   30
    · Test · 测试(自我测试,修改代码,提交修改)   60   120
    Reporting 报告 180   150
    · Test Report · 测试报告   150   120
    · Size Measurement · 计算工作量   10   10
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划   20  20
    合计   510  990

    3 解题思路

            为了稍微好上手,还是选择了最熟悉的C语言。

            1.根据要求,随机生成四则运算的长度(操作符个数小于10),n=rand()%10+1,生成操作数个数;

            2.操作数随机生成,保存在整形数组a[n]中,其中a[2i]时保存的1~100的数字,rand()%100+1,所以后面不会再考虑除数是否为0;

            3.把分数也看成除法,所以整个式子就是整数的加减乘除,在这里,把a[2i+1]里面的数看成操作符,rand()%4-4,随机生成的-4、-3、-2、-1分别代表“+”、“-”、“*”、“/”;

            4.能够保存用户的输入,并判断对错,我的想法是把最后结果转化为字符串,用户的输入也用字符串保存(如果输入为整数则只与最后结果‘/’之前的字符串进行比较),进行字符串匹配,判断是否正确;

            5.计算正确率,只需要用一个count来记录即可,最后count*100/n,然后用%.2f表示即可;

            6.其中关键就是如何计算这个四则运算式,在我考虑了乱七八糟的很长时间后,室友提醒我用逆波兰式,然后就百度,看了一位博主的分析,原理分析很细致,然后就顺着这个思路来往下继续写。主要是将结果保存在另外一个整型数组中,得到最终结果后,转化为字符串。

            总结一下,大致为: 随机运算符个数、随机操作数、随机运算符保存在数组中-->然后转化为后缀表达式-->计算后缀表达式-->与输入的结果进行匹配

    4设计实现和代码说明

            有4个被调函数,生成表达数create()函数,转换后缀表达式trans()函数、后缀表达数计算calculate()函数、最大公约数gcd()函数(用于分数化简)。

    4.1 随机运算符个数、操作符、运算符的生成

             C语言中有生成随机数的函数,因为对每句代码如何写还是不知道,所以每写一句就会百度一下,过程中才知道应该使用srand()函数,然后写在主函数中:

    void int main()
    {
        int n,i,c;
        printf("请输入需要生成的四则运算式的个数:");
        scanf("%d",&c);
        for(i=0;i<n;i++)
        {
          srand( (unsigned int)time( NULL ) ); //初始化随机数
          n=rand()%10+1;//随机生成表达式长度,有1~10个操作符
          //生成运算表达式等等操作
         } 
            //其他操作
    }

    4.2生成运算表达式

     随机生成四则运算表达式create()函数:

    int create(int n,int a[])
     {
         //首先随机生成一个运算表达式 
         int m,i,j,t,top=0; 
         m=2*(n-1);//表达式有多少个操作数,就要用相应长度的数组来保存     
         
        //随机生成表达式 
        for(i=0;i<=m;i++)
        {
            if(i%2==0)
            {
                a[i]=rand()%100+1;//1~100之间的数,所以后面也无需判断除数是否为零。 
            }
            else 
            {
                j=rand()%4-4;//因为用整型保存,所以使用-4,-3,-2,-1分别表示+,-,*,/ 
                a[i]=j; 
            }
            if(a[i]==-4) printf("%c",'+');
            else if(a[i]==-3) printf("%c",'-');
            else if(a[i]==-2) printf("%c",'*');
            else if(a[i]==-1) printf("%c",'/');
            else printf("%d",a[i]);//输出表达式 
        }
        printf("=
    "); 
    }
    create函数

    4.3转化为后缀表达式

            转化为后缀表达式trans()函数:

    int trans(int n,int *a)
        {
          int i=0,j=0,top=0;
          int t=a[i++]; //保存当前a[i]的值 
          int b[2*(n-1)];//保存后缀表达式
          int stack[2*(n-1)];//作为栈使用 
          while(i<=2*(n-1))
         {
            switch(t)
            {
                case -4:/*判定为加减号*/
                case -3:
                    while(top!=0)
                    {
                        b[j]=stack[top];
                        top--;j++;
                    }
                    top++;
                    stack[top]=t;
                    break;
                case -2:
                case -1:
                    while(stack[top]==-2||stack[top]==-1)
                    {
                        b[j]=stack[top];
                        top--;j++;
                    }
                    stack[++top]=t;
                    break;
                default://默认为数字 
                    while(t>=0&&t<=100)
                    {
                        b[j]=t;j++;
                        t=a[i];i++;
                    }
            }
        }
        while(top!=0)
        {
            b[j]=stack[top];
            j++;top--;
        } 
    }
        
    trans函数

    4.4计算后缀表达式

            计算后缀表达式calculate()函数,将第一个数保存在r[3]中。r[1]固定为-1,代表除号,用户每次计算都是取一个操作数与r[0](分子)或者r[2](分母)进行运算;

        //计算后缀表达式,并将结果转化为字符串 
    void calculate(int n,int b[],char rs1[]) 
    {
        int    i=0,t,top=0;
        int stack[2*(n-1)]={0};
        int r[3]={0,-1,1};//保存最后结果,初始情况下,分子为0,分母为,1 
         
                                //rs1保存最后正确结果的分子 
         char rs2[2*(n-1)]={' '};//最后结果的分母用字符串表示 
           t=b[i];i++;
        while(i<=2*(n-1))
        {
            switch(t)
            {
              case -4:r[0]=r[0]+stack[top]*r[2];top--;break;//+
              case -3:r[0]=stack[top]*r[2]-r[0];top--;break;//-
              case -2:r[0]=r[0]*stack[top];top--;break;//*
              case -1:r[2]=r[2]*stack[top];top--;break;
              default: top++;stack[top]=t;    
            }
             t=b[i++];     
        }
        //化简最终结果
        r[0]=r[0]/gcd(r[0],r[2]);
        r[2]=r[2]/gcd(r[0],r[2]); 
        //将整形转化成字符串 
        itoa(r[0],rs1,10);
        itoa(r[2],rs2,10);
        strcat(rs1,"/");//字符串拼接 
        strcat(rs1,rs2);
        
    }
    calculate()函数

    4.5求最大公约数

            为了化简最后的分数,所以写了一个求最大公约数的函数。

    5.运行结果

            运行结果如图:因为之前没有报错,然后就一直在写,只是写的被调函数trans()的测试程序发现闪退,找不到原因,然后想起来用VS测试,但是发现现在来不及了。所以整个代码现在是,没有错,但是跑不出结果的状态,等后面再补充!!!

    6.项目小结

            虽然是个很小的项目,再看了其他同学的博客后,很多都说很简单,最开始没有形成具体的思路,所以一下子上手总是卡壳。最开始想的是生成的运算符就用字符串保存,后面自己进行不下去了。后面想着看一下其他同学的代码,从他们规范的定义到用重载,这些或许在老师看来很简单的东西,我一下子都有点懵,现在想想,一个星期这么长时间,自己静下心来,足以把这个东西搞明白,但是我没有想其他同学那样,遇到问题,能静下心来一点一点分析,最后自己把知识点琢磨透彻。于是就按照自己特别low的想法来一步一步写,最后的最后还是出现很多问题,这个程序思路很简单,代码量也很小,但是就是出现没有错误,运行不出来的情况,然后我才想起来没有做测试,于是就单独对每个被调函数测试,发现是转化为后缀表达式trans()函数有问题。后面计算函数依然是这样。慢慢体会到测试的重要性,并且也明白,在编程阶段,不能确保当前代码正确的实现功能的时候,千万不能继续往下赶。还有就是同样时间,自己却没有做出来,学习方法和学习策略确实有问题,下来会和同学多交流,也会继续把这个代码结果跑出来。

  • 相关阅读:
    bash 大致学习后的小案例,导出数据进行打包
    android 处理图片工具
    js屏蔽文本选中产生的蓝色背景色
    修正IE6不支持position:fixed的bug
    TreeView ShowCheckBox [文摘]
    存储过程分页程序
    GridView 72般绝技 很棒的东西 收藏..
    GridView 自带排序分页
    字符串补位
    sql2005 定义临时表
  • 原文地址:https://www.cnblogs.com/shuangshuangblog/p/7599952.html
Copyright © 2020-2023  润新知