结对项目:四则运算

1、Github地址:https://github.com/JXQQQ/calculateHomework

      项目成员:3218005038高子茵  3218005039江晓琦

2、项目要求

  使用 -n 参数控制生成题目的个数。(已完成)
 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围。(已完成)  
 生成的题目中如果存在形如e1÷ e2的子表达式,那么其结果应是真分数。(已完成)
 每道题目中出现的运算符个数不超过3个。(已完成)
 程序一次运行生成的题目不能重复。(未完成)
 生成的题目存入执行程序的当前目录下的Exercises.txt文件。(已完成)
 在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件。(已完成)
 程序应能支持一万道题目的生成。(已完成)
 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计。(未完成)

3、效能分析

由于需求9没有完成,只完成了一个手动输入答案后对答案的需求;因此,在效能分析得时候我们删去对答案部分的代码,防止手动输入答案的时间造成影响。

如图分别为生成20、1000、10000道题所需要的时间。

4、设计实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?

 

5、代码说明。

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<time.h>
  4 #include"head.h"
  5 #include"function.c"
  6     int an[3];//存入用户答案的全局变量
  7 int main(struct formula f){
  8   int opernum;//符号数
  9   int typeflag,operflag=0;
 10   int r,i,j,k,t,n,repeat;
 11   int bktflag=1;
 12   int tnumber,numflag=1,m=0;
 13   FILE *file;
 14   createFile("Answers.txt");
 15   FILE *fp=fopen("Answers.txt","a+");
 16   struct num answers;
 17   createFile("Exercises.txt");
 18   printf("\n");
 19   file=fopen("Exercises.txt","a+");
 20   if(file==NULL) {
 21         printf("No File.\n");
 22          return 0;}
 23   printf("please enter the range:\n");
 24   scanf("%d",&r);
 25   printf("please enter the number of exercises:\n");
 26   scanf("%d",&tnumber);
 27   struct formula fmls[tnumber+1];
 28   int ran[tnumber+1][3];
 29   srand(time(NULL));
 30   while(numflag<tnumber+1){
 31    opernum=rand()%3+1;//确定运算符数量
 32    f.numcount=opernum+1;//运算数个数
 33    for(i=0;i<4;i++) f.figure[i].den=1;//整数时分母为1
 34    for(i=0;i<f.numcount;i++){
 35      f.figure[i].mol=rand()%r+1;
 36      typeflag=rand()%100;//1时为真分数
 37      if(typeflag==1)
 38          f.figure[i].den=rand()%50+1;
 39          if(f.figure[i].den==1||f.figure[i].mol%f.figure[i].den==0)
 40              f.figure[i].den=rand()%r+1;
 41          k=gcd(f.figure[i].mol,f.figure[i].den);
 42          f.figure[i].mol=f.figure[i].mol/k;
 43          f.figure[i].den=f.figure[i].den/k;//化简
 44      }//确定运算数
 45    for(i=0;i<4;i++){
 46      t=rand()%4;
 47      switch(t){
 48        case 0:f.oper[i]='+';break;
 49        case 1:f.oper[i]='-';break;
 50        case 2:f.oper[i]='*';break;
 51        case 3:f.oper[i]='/';break;
 52      }
 53    }//确定符号
 54    for(i=0;i<5;i++) f.brackets[i]=0;
 55    if(f.numcount==3){
 56      n=rand()%3;
 57      switch(n){
 58        case 0: bktflag=0;
 59         break;
 60        case 1: {
 61            for(i=0;i<4;i++) f.brackets[i]=0;
 62            f.brackets[0]=1;f.brackets[1]=1;}
 63        break;
 64        case 2:{
 65            for(i=0;i<4;i++) f.brackets[i]=0;
 66            f.brackets[1]=1;f.brackets[2]=1;}
 67        break;
 68    }
 69   }//3个运算数
 70   if(f.numcount==4){
 71      n=rand()%7;
 72      switch(n){
 73         case 0:bktflag=0;
 74          break;
 75         case 1:{
 76          for(i=0;i<4;i++) f.brackets[i]=0;
 77          f.brackets[0]=1;f.brackets[1]=1;}
 78          break;
 79         case 2:{
 80          for(i=0;i<4;i++) f.brackets[i]=0;
 81          f.brackets[0]=1;f.brackets[2]=1;}
 82          break;
 83         case 3:{
 84           for(i=0;i<4;i++) f.brackets[i]=0;
 85           f.brackets[1]=1;f.brackets[2]=1;}
 86          break;
 87         case 4:{
 88          for(i=0;i<4;i++) f.brackets[i]=0;
 89          f.brackets[1]=1;f.brackets[3]=1;}
 90          break;
 91         case 5:{
 92           for(i=0;i<4;i++) f.brackets[i]=0;
 93           f.brackets[2]=1;f.brackets[3]=1;}
 94          break;
 95         case 6:{
 96          for(i=0;i<4;i++) f.brackets[i]=1;}
 97          break;
 98      }
 99   }//确定括号
100   for(i=1,repeat=0;i<=numflag;i++){
101         if(ifRepete(f,fmls[i])==TRUE) {
102             repeat=1;
103             break;
104         }
105   }
106   if(repeat==1) break;
107   answers=calculateFml(f);//计算答案
108   if(answers.mol<0||answers.den<0){//舍去负值式子
109     continue;
110   }
111   printf("%d. ",numflag);//打印并录入式子和答案
112   fprintf(file,"%d. ",numflag);
113   printFormula(f);
114   fmlInFile(file,f);
115   fprintf(fp,"%d. ",numflag);
116   numInFile(fp,answers);
117   int g=gcd(answers.mol,answers.den);//将答案分解成三部分存入
118   if(g>1){
119         answers.den/=g;
120         answers.mol/=g;
121     }
122      ran[numflag][2]=answers.den;
123      ran[numflag][0]=answers.mol/answers.den;
124      ran[numflag][1]=answers.mol%answers.den;
125     numflag++;
126  }
127  //输入答案
128  printf("Please input your answer:\n");
129  int result[tnumber+1];
130  for(i=1;i<=tnumber;i++){
131     char input[10];
132     struct num c1;
133     printf("%d. ",i);
134     fflush(stdin);
135     gets(input);
136     getAnswers(input);
137     result[i]=1;//判断对错
138     for(j=0;j<3;j++){
139         if(an[j]!=ran[i][j]) {result[i]=0;break;}
140     }
141  }
142     int correct=0,wrong=0;
143     printf("Correct:(");
144     for(i=1;i<=tnumber;i++){
145         if(correct>0) printf(",");
146         if(result[i]==1) {
147                 printf("%d",i);
148                 correct++;
149         }
150     }
151     printf("),共%d题\n",correct);
152     printf("Wrong:(");
153     for(i=1;i<=tnumber;i++){
154         if(wrong>0) printf(",");
155         if(result[i]==0) {
156                 printf("%d",i);
157                 wrong++;
158         }
159     }
160     printf("),共%d题\n",wrong);
161  printf("\nOK:you can check the file.\n");
162 return 0;
163 }
main
#ifndef TEST_H
#define TEST_H
#define NULL 0
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INTE 0 //整数
#define FRAC 1 //分数
#define MAXSIZE 10001
typedef int Status;
struct num {//数据
    int mol;//分子
    int den;//分母(整数默认为1)
};
struct formula{//式子
    int numcount;//运算数的个数
    struct num figure[4];//运算数的数组
    char oper[4];//符号的数组(默认oper[0]==NULL)
    Status brackets[4];//括号数组
};
extern struct num calculateFml(struct formula fml);
extern struct num getAnswer(char an[]);
extern int an[3];
#endif
head.h
  1 void createFile(char filename[]){//创建文件,已存在则覆盖
  2     FILE *fp;
  3     fp=fopen(filename, "w");//写入文件
  4     if(fp==NULL) printf("文件创建失败");
  5     else printf("文件%s创建成功!",filename);
  6     fclose(fp);
  7 }
  8 void printFormula(struct formula fml){//打印一个式子
  9     int flag=0,bflag=0;//出现单括号时flag=1,已打印括号时bflag=1
 10     int i;
 11     for(i=0,flag=0;i<fml.numcount;i++){
 12         bflag=0;
 13         if(i>0) {
 14                 if(fml.oper[i]=='/') printf("÷");
 15                 else if(fml.oper[i]=='*') printf("×");
 16                 else printf("%c",fml.oper[i]);
 17             }
 18         if(fml.brackets[i]==TRUE&&flag==0&&bflag==0){
 19             printf("(");
 20             flag=1;
 21             bflag=1;
 22         }
 23         printNum(fml.figure[i]);
 24         if(flag==1&&fml.brackets[i]==TRUE&&bflag==0) {
 25             printf(")");
 26             flag=0;
 27         }
 28     }
 29     printf("=\n");
 30 
 31 }
 32 void printNum(struct num c1){//真分数打印一个数
 33         int g=gcd(c1.mol,c1.den);
 34         if(g>1){
 35             c1.den/=g;
 36             c1.mol/=g;
 37         }
 38         if(c1.den==1) printf("%d",c1.mol);
 39         else if(c1.den<c1.mol){
 40             int z=c1.mol/c1.den;
 41             int r=c1.mol%c1.den;
 42             printf("%d'%d/%d",z,r,c1.den);
 43         }else printf("%d/%d",c1.mol,c1.den);
 44         return ;
 45 }
 46 void fmlInFile(FILE *fp,struct formula fml){//写入文件:式子
 47     if(fp==NULL){
 48         printf("式子写入失败");
 49     }else{
 50         int flag,bflag=0;//出现单括号时为1
 51         int i;
 52         for(i=0,flag=0;i<fml.numcount;i++){
 53                 bflag=0;
 54             if(i>0) {
 55                 if(fml.oper[i]=='/') fprintf(fp,"÷");
 56                 else if(fml.oper[i]=='*') fprintf(fp,"×");
 57                 else fprintf(fp,"%c",fml.oper[i]);
 58             }
 59             if(flag==0&&fml.brackets[i]==TRUE&&bflag==0){
 60                 fprintf(fp,"(");
 61                 flag=1;
 62                 bflag=1;
 63             }
 64 
 65             int g=gcd(fml.figure[i].mol,fml.figure[i].den);//打印式子中的数
 66             if(g>1){
 67                 fml.figure[i].den/=g;
 68                 fml.figure[i].mol/=g;
 69             }
 70             if(fml.figure[i].den==1) fprintf(fp,"%d",fml.figure[i].mol);
 71             else if(fml.figure[i].den<fml.figure[i].mol){
 72                 int z=fml.figure[i].mol/fml.figure[i].den;
 73                 int r=fml.figure[i].mol%fml.figure[i].den;
 74                 fprintf(fp,"%d'%d/%d",z,r,fml.figure[i].den);
 75             }else fprintf(fp,"%d/%d",fml.figure[i].mol,fml.figure[i].den);
 76             if(flag==1&&fml.brackets[i]==TRUE&&bflag==0) {
 77                 fprintf(fp,")");
 78                 flag=0;
 79             }
 80         }
 81     fprintf(fp,"=\n");
 82     }
 83     return 0;
 84 }
 85 void numInFile(FILE *fp,struct num c1){//写入文件:真分数
 86     if(fp==NULL){
 87         printf("数据写入失败");
 88     }else{
 89         int g=gcd(c1.mol,c1.den);
 90         if(g>1){
 91             c1.den/=g;
 92             c1.mol/=g;
 93         }
 94         if(c1.den==1) fprintf(fp,"%d",c1.mol);
 95         else if(c1.den<c1.mol){
 96             int z=c1.mol/c1.den;
 97             int r=c1.mol%c1.den;
 98             fprintf(fp,"%d'%d/%d",z,r,c1.den);
 99         }else fprintf(fp,"%d/%d",c1.mol,c1.den);
100        fprintf(fp,"\n");
101     }
102     return ;
103 }
写入文件
struct formula simplifyBracket(struct formula fml){//递归化简括号
    int i=0;
    struct num temp;
    struct formula ff;;
    for(i=0;i<fml.numcount;i++){
        if(fml.brackets[i]==TRUE){
                int j,k,count;
                if(fml.brackets[i+1]==0) count=3;
                else count=2;
                if(count==2) {//括号中只有2数
                    temp=calculate(fml.figure[i],fml.figure[i+1],fml.oper[i+1]);//计算括号内式子
                    fml.figure[i]=temp;
                    fml.brackets[i]=0;
                    fml.numcount--;
                    i++;
                    for(;i<fml.numcount;i++){
                        fml.figure[i]=fml.figure[i+1];
                        fml.oper[i]=fml.oper[i+1];
                        fml.brackets[i]=fml.brackets[i+1];
                    }
                }
                if(count==3){
                    ff.numcount=count;
                    k=i;
                    for(j=0;j<3;j++,k++){
                        ff.figure[j]=fml.figure[k];
                        ff.oper[j]=fml.oper[k];
                        ff.brackets[j]=0;
                    }
                    ff=simplifyMD(ff);
                    ff=simplifyAS(ff);
                    fml.figure[i]=ff.figure[0];
                    fml.brackets[i]=0;
                    if(i<fml.numcount-3){
                        fml.figure[i+1]=fml.figure[i+3];
                        fml.oper[i+1]=fml.oper[i+3];
                        fml.brackets[i+1]=fml.brackets[i+3];
                    }
                    fml.numcount-=2;
                }
                fml=simplifyBracket(fml);
        }
    }
    return fml;
}
struct num calculate(struct num c1,struct num c2,char oper0){//两数运算
    switch(oper0){
    case'+':
        return addCount(c1,c2);
    case'-':
        return subCount(c1,c2);
    case'*':
        return mulCount(c1,c2);
    case'/':
        return divCount(c1,c2);
    default:
        printf("计算失效!");
        return c1;
    }
}
计算答案

6、测试运行。

 

经过多次抽取题目进行人工运算,再与答案进行比对,得到答案与生成的答案一致。

7、PSP表格

PSP2.1

Personal Software Process Stages

预估耗时(小时)

实际耗时(小时)

Planning

计划

 1

1.5 

· Estimate

· 估计这个任务需要多少时间

 0.5

1

Development

开发

 38

48.2

· Analysis

· 需求分析 (包括学习新技术)

6

· Design Spec

· 生成设计文档

· Design Review

· 设计复审 (和同事审核设计文档)

0.2 

0.2 

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

0.8 

· Design

· 具体设计

· Coding

· 具体编码

15 

16 

· Code Review

· 代码复审

· Test

· 测试(自我测试,修改代码,提交修改)

10 

15 

Reporting

报告

· Test Report

· 测试报告

· Size Measurement

· 计算工作量

0.5 

0.5 

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

 0.5

0.5 

合计

 

 40.5

 51.7

8、项目小结

  高子茵:本次结对项目中,学习到了很多平时做编程作业学习不到的东西。比如说关于file文件函数的使用。但是仍有问题没有解决,比如说在随机运算数的过程中控制 不好分数出现的概率;在本次结对项目中明白了注释的重要性,会比平时写多点的注释。跟搭档的配合挺好的,用腾讯会议一起改bug,有时候我的一些奇奇怪怪的错误她都能帮我找出来。

 江晓琦:本次作业是我的第一次结对项目,我获得了很多宝贵的经验。项目开始之前我们讨论了很久,前期的任务分配和有效的沟通能大大提高我们的编程效率。我们选择了最熟悉的c语言,用结构体的方式定义式子和运算数。编程的过程并不顺利,依然需要边自学边编程,某些需求也没有完全实现,判重也只是最初步浅显的水平。我的搭档高子茵总是很耐心地跟我沟通、相互鼓励,有不懂的地方会及时给我帮助,即使我有因为表达不当而犯错的时候她也静下心来和我一起解决问题,一起修改代码。

posted @ 2020-04-14 22:23  室友天天吃宵夜  阅读(199)  评论(0编辑  收藏  举报