结对编程第二阶段

一、实验目标

  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的分享屏幕功能和邀请对方远程协助功能实现交流互换角色,如下图是远程协助截图,对方可以控制你的鼠标和键盘。

 

 结对编程第二阶段_第1张图片

 

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张图片

 

 

结对编程第二阶段_第3张图片

 

 

结对编程第二阶段_第4张图片

 

 

2.遇到的问题及讨论

   A.我先屏幕分享,一起分析了题目的几种选择(如定长随机长度),进行讨论确定类型。这里我们犯了一个很蠢的错误,我们一开始选择的是随机长度手动输入。我们设定了随机函数,产生随机式子长度p(0

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

结对编程第二阶段_第5张图片

 

 

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

 

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

 

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

 

   结对编程第二阶段_第6张图片

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

A.源代码

#include
#include
#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 == '\n') 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 '\n':
        {
            if(ch == '\n') return '=';
            else return '<';
        }
            break;
    }
}
int Calculate(int num1, char ch, int num2)
{
    int result;
    switch(ch)
    {
        case '+':
            result = num1 + num2;
            break;
        case '-':
   if(num1
   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, '\n');
    ch = getchar();
    while((ch != '\n') || (GetOperateSymbol(&symbol) != '\n'))
    {
        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("恭喜您答对了\n");
     }
     else{
      printf("哦,您答错了,正确答案是:%d\n",result);
     }
  }
  else{
   printf("不符合规则,请重新出题\n");
  }
  
 }
 printf("您答对了%d题\n",cj/10);
 printf("您的总分为%d\n",cj);
}
 
B.运行截图

     结对编程第二阶段_第7张图片

 

C.托管代码

结对编程第二阶段_第8张图片

 

 

 结对编程第二阶段_第9张图片

 

七、实验总结

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

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

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(结对编程第二阶段)