• 结对编程第二阶段


    一、实验目标

      1)体验敏捷开发中的两人合作。
      2)进一步提高个人编程技巧与实践。
    二 、实验内容
      1)根据以下问题描述,练习结对编程(pair programming)实践;
      2)要求学生两人一组,自由组合。每组使用一台计算机,二人共同编码,完成实验要求。
      3)要求在结对编程工作期间,两人的角色至少切换 4 次;
      4)编程语言不限,版本不限。建议使用 Python 或 JAVA 进行编程。

    队员博客地址:

             王锦(https://www.cnblogs.com/wjin/) 张子毓(https://www.cnblogs.com/lingluan23333/)  四则运算 

    github仓库地址

             https://github.com/Wjinfiny/daimaqiaobu


    三、实验过程
    1.确定运算式长度——定长或随机
       定长:简单
         假设两个运算符,不需要堆栈,前后两个运算符比较,优先级高的先运算,结果再与剩下的数运算即可;如果是三个,也可以用这个方法,相对于堆栈都相对简单
     随机:使用堆栈;随机又可以分情况(手动输入运算式或随机产生运算式)
     {
       A.手动输入
       B.随机产生 随机产生式子长度,随机产生运算式和运算符
    }
        经过讨论我们认为定长相对简单,没有挑战性;而随机产生运算式较为复杂,有两个随机需要处理。在时间相对不是十分充裕的情况下,我们选择了中间难度
    的手动输入
     
     
    2、确定数据结构
        随机式子长度,手动输入确定后,我们接下来讨论了使用什么数据结构。结合上次第一阶段的讨论,我们决定用堆栈实现式子运算。
     
    3、确定交流工具
        我们选择用QQ的分享屏幕功能和邀请对方远程协助功能实现交流互换角色,如下图是远程协助截图,对方可以控制你的鼠标和键盘。

     

     

    4.根据功能划分模块,定义接口

      A.功能模块图

    B.函数名(接口)

    1.OperateNum:运算数
    2.OperateSymbol:运算符
    3.GetOperateNum:取数
    4.GetOperateSymbol:取符
    5.PushOperateNum:数进栈
    6.PushOperateSymbol:数进栈
    7.PopOperateNum:数退栈
    8.PopOperateSymbol:符退栈
    9.IsOperateSymbolOrNum(char ch):判断输入的符号是否是四则运算符号
    10.Priority(char inputnum, char ch):判断符号的优先级
    11.Calculate(int num1, char ch, int num2):两数运算
    12.MainCalc()//于用户输入和计算结果
    13.int main()//主函数

    五、实验遇到的困难及交流讨论

    1.角色分工

    上述函数1、2、3、4、5、6、7、8、12是我编写的,9、10、11、13为张子毓编写的

     我先编写1~8,运算数和运算符的定义及简单的入栈出栈销毁栈取栈顶;张子毓编写判断输入的符号是否是四则运算符号、判断符号的优先级、两数运算;再次交换角色,我编写MainCale()函数(于用户输入和计算结果)整合张子毓前面的编写的三个函数;最后张子毓编写主函数。

    2.遇到的问题及讨论

       A.我先屏幕分享,一起分析了题目的几种选择(如定长随机长度),进行讨论确定类型。这里我们犯了一个很蠢的错误,我们一开始选择的是随机长度手动输入。我们设定了随机函数,产生随机式子长度p(0<p<=4)。代码编写的中途,在张子毓的提醒下,突然醒悟,手动输入就是随机式子长度。

       B.在输入式子的过程中,出现如下错误

    (这是正确代码完成后的错误还原,原来的错误更严重,只能输入第一个式子,其他式子没有办法输入)

    我们修改了好久,以为是MainCala()函数(计算答案的函数)调用出了问题,后来反复修改,使用printf找错误,最后发现是错把回车当成了输入字符,修改代码添加了getchar()

    C.两数运算这部分是张子毓写的,但一开始她没有想到不符合题目规范的式子不予计算的情况。角色互换后,我修改代码,将两数运算中会出现不规范的“-”和“/”做出了修改,设置出错情况下result=-1000,这样就主函数进行判断,就不会计算不规范的式子

      

    六,代码及运行截图及托管代码

    A.源代码

    #include <stdio.h>
    #include <stdlib.h>
    #define MAX 20
    //定义两个栈,分别存放运算数和运算符
    struct SNode_Num
    {
        int datas[MAX];
        int top;
    };
    typedef struct SNode_Num OperateNum;
    struct SNode_Symbol
    {
        char symbol[MAX];
        int top;
    };
    typedef struct SNode_Symbol OperateSymbol;
     
    //取出相应的数
    int GetOperateNum(OperateNum *StackNum)
    {
        return StackNum->datas[StackNum->top];
    }
     
    //取出相应运算符
    char GetOperateSymbol(OperateSymbol *StackSymbol)
    {
        return StackSymbol->symbol[StackSymbol->top];
    }
     
    //运算数进栈
    void PushOperateNum(OperateNum *StackNum, int x)
    {
        StackNum->top++;
        StackNum->datas[StackNum->top] = x;
    }
     
    //运算符进栈
    void PushOperateSymbol(OperateSymbol *StackSymbol, char ch)
    {
        StackSymbol->top++;
        StackSymbol->symbol[StackSymbol->top] = ch;
    }
     
    //运算数退栈
    int PopOperateNum(OperateNum *StackNum)
    {
        int num;
        num = StackNum->datas[StackNum->top];
        StackNum->top--;
        return num;
    }
     
    //运算符退栈
    char PopOperateSymbol(OperateSymbol *StackSymbol)
    {
        char ch;
        ch = StackSymbol->symbol[StackSymbol->top];
        StackSymbol->top--;
        return ch;
    }
     
    //判断输入的符号是否是四则运算符号
    int IsOperateSymbolOrNum(char ch)
    {
        if(ch == '+' || ch == '-' || ch == '*'|| ch == '/' || ch == ' ') return 1;
        else return 0;
    }
     
    //判断符号的优先级
    char Priority(char inputnum, char ch)
    {
        switch(inputnum)
        {
            //加减在同一个优先级上
            case '+':
            case '-':
            {
                if(ch == '+' || ch == '-') return '>';
                else if(ch == '*' || ch == '/') return '<';
                else return '>';
            }
                break;
     
            //乘除在同一优先级
            case '*':
            case '/':
            {
                if(ch == '+' || ch == '-') return '>';
                else if(ch == '*' || ch == '/') return '>';
                else return '>';
            }
                break;
     
            case ' ':
            {
                if(ch == ' ') return '=';
                else return '<';
            }
                break;
        }
    }
    int Calculate(int num1, char ch, int num2)
    {
        int result;
        switch(ch)
        {
            case '+':
                result = num1 + num2;
                break;
            case '-':
       if(num1<num2)
       result=-1000;
       else
       result=num1-num2;
                break;
            case '*':
                result = num1 * num2;
                break;
            case '/':
       if(num1%num2==0)
                result = num1 / num2;
       else
        result=-1000;
        }
        return result;
    }
    //用于用户输入和计算结果
    int MainCalc()
    {
        //主函数进行计算
        OperateNum datas;
        OperateSymbol symbol;
        int num1, num2, result, num;
        char ch, sign;
     //初始化顺序栈
     datas.top=-1; //操作数栈顶指针
     symbol.top=-1; //操作符栈顶指针
        //把回车计算的操作符放在栈中
        PushOperateSymbol(&symbol, ' ');
        ch = getchar();
        while((ch != ' ') || (GetOperateSymbol(&symbol) != ' '))
        {
            if(!IsOperateSymbolOrNum(ch))
            {
                num = atoi(&ch);  //将字符转换为整数
                ch = getchar();   //获取输入
                while(!IsOperateSymbolOrNum(ch))
                {
                    num = num * 10 + atoi(&ch);
                    ch = getchar();   //当没有输入回车时,继续获取输入
                }
                PushOperateNum(&datas, num);
            }
            else
            {
       //考虑第一个数是负数的情况
       if(ch=='-'&&symbol.top==0&&datas.top==-1)PushOperateNum(&datas, 0);
                switch(Priority(GetOperateSymbol(&symbol), ch))
                {
                    //判断优先级后进行计算
                    case '<':
                        PushOperateSymbol(&symbol, ch);
                        ch = getchar();
                        break;
                    case '=':
                        sign = PopOperateSymbol(&symbol);
                        ch = getchar();  //获取输入
                        break;
                    case '>':
                        sign = PopOperateSymbol(&symbol);
                        num2 = PopOperateNum(&datas);
                        num1 = PopOperateNum(&datas);
                        result = Calculate(num1, sign, num2);
                        PushOperateNum(&datas, result);
                        break;
     
                }
            }
        }
        result = GetOperateNum(&datas);
        return result;
    }
     
    int main(int argc, char *argv[])
    {
        int result,cj=0,answer,i;
      
        for(i=0;i<10;){
         getchar();
          printf("请第%d出题:",i+1);
         result = MainCalc();
           if(result>=0){
          i++;
            printf("请输入你的答案:");
            scanf("%d",&answer);
         if(result==answer){
          cj+=10;
          printf("恭喜您答对了 ");
         }
         else{
          printf("哦,您答错了,正确答案是:%d ",result);
         }
      }
      else{
       printf("不符合规则,请重新出题 ");
      }
      
     }
     printf("您答对了%d题 ",cj/10);
     printf("您的总分为%d ",cj);
    }
     
    B.运行截图

         

    C.托管代码

     

    七、实验总结

    1.有点累,早上九点一直到现在,中间吃了半个小时的饭,其他时间一直都在弄。

    2.收获很多,结对编程相对于一个人编程,出现错误的几率更小。我在编写时张子毓的提醒一直都很致命,因为一般都是我没有注意到的错误,一提醒意味着又要修改了。之前一个编程是,经常会犯一些小错误,但是没有发现,编译后发现错误了,又很难找到。所以结对编程降低了代码的错误率。同时结对编程,队友相互鼓励,在出现错误的时候会更平静的处理。不会崩溃的说:“啊,又错了!”。

    3.通过这次实验也了解到托管的用法,对以后也受益很多,比如以后编写的代码、毕业论文等等,都可以托管保存。再也不用担心丢失了,对于我这种丢三落四的人,简直太棒了。

     
     
     
  • 相关阅读:
    [转载]ASP.NET中IsPostBack详解
    [转载]论asp.net out、ref、return
    用CSS让字体在一行内显示不换行
    改变时间格式的方法
    JS方法的使用
    [转载] iframe嵌入网页的用法
    iphone6 inline-flex兼容问题
    ActionResult的其它返回值
    为什么java中只允许继承一个类?
    关于asp.net MVC3 ----@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction
  • 原文地址:https://www.cnblogs.com/wjin/p/12587062.html
Copyright © 2020-2023  润新知