• 结对编程项目阶段性进展


    第一阶段目标 - 能把计算的功能封装起来,通过测试程序和API 接口测试其简单的加法功能。

      因为原本的设计,就设计了计算器类,将其封装好了,所以直接跳过了第一阶段。

    第二阶段目标 - 通过测试程序和API 接口测试其简单的加减乘除功能。并能看到代码覆盖率。

      

      可以从图中看出,正负小数,正负分数等结果的计算正确性

      而计算器类的使用也非常方便,如下代码

    Calculator cal("1+1");        //初始化计算器类
    cal.recalculator("1+1");    //可重复调用的计算函数
    cal.run();                        //计算结果
    cal.getMyResult();            //获得计算结果,为string类型

    第三阶段目标 - 通过测试程序和API 接口测试对于各种参数的支持。并能看到代码覆盖率。 

      第三阶段中加入了三个辅助计算的参数,故对此修改计算器类,此部分代码还添加了出错处理,后续部分会说明,添加代码如下:

    public:
            MyError setDateRange(int type){                //设置数据范围 
            if(0<type){
                daterange=type;
                return ERROR_NO;
            }
            else
                Error=ERROR_SET;
            return ERROR_SET;
        } 
        
        MyError setMaxUnit(int num){                //设置最大识别数量 
            if(0<num&&num<=80){
                maxunit=num;
                u=new unit[maxunit];             //清空后缀表达式 
                this->num=0; 
                return ERROR_NO;
            }
            else
                Error=ERROR_SET;
            return ERROR_SET;
        }
        
        MyError setAccuracy(int a){                    //设置精度 
            if(a>=-1&&a<=6){
                accuracy=a;
                return ERROR_NO;
            }
            else
                Error=ERROR_SET;
            return ERROR_SET;
        }
    private:
        //非辅助计算参数,设置后,除非重复设置,否则不会被clear之类的清除 
        int daterange;                    //算式参数中数据的范围 
        int maxunit;                    //算式参数最多能识别的字符数量 
        int accuracy;                    //小数精确位数,-1为不精确,即去掉所有末尾的0,其他数字即小数点后保留的位数 

      daterange参数,表示计算器类只能计算-daterange到daterange之间的数据,故如果计算结果超出范围,就会报超出范围的错,默认为100000

      maxunit参数,代表输入的算式参数最多含有几个字符,超出字符会报非法算式的错误,默认为80

      accuracy参数,代表最后输出的计算结果的精度,-1代表原样输出,0-6代表,具体保留几位小数,采取四舍五入。

    enum MyError{ERROR_NO=0,ERROR_SET=1,ERROR_OPERATOR=2,ERROR_ZERO=4,ERROR_STRING=8,ERROR_RANGE=16};

      新定义的错误枚举类型,包含了所有计算器类会报的错误,并且将原本计算器类中的bool类型的error替换成了MyError类型的Error,里面存储的上一个错误类型,默认为ERROR_NO(没错误)

      并且将原先所有返回-1的代码,全部替换成了返回具体错误类型

      

      在程序最开始调用了cal.setDateRange(1); 函数,即设置计算器类只能计算-1到1的数,结果如上图,只有第一题还能计算,余下所有题目会报错,并会显示错误类型,其他错误类型也是如此,就不过多展示了

      

    第四阶段目标 -界面模块,测试模块和核心模块的松耦合。

       因为,界面模块的代码还没有写完,所以,第四阶段为下一周的任务,我会和同组的一起攻克这一阶段的目标的

    下面是目前所有的代码

      1 #include <iostream>
      2 using namespace std; 
      3 #include <string.h>
      4 #include <stack>
      5 #include <sstream>
      6 #include <fstream>
      7 #include <stdlib.h>
      8 #include <stdio.h>
      9 #include <math.h>
     10 
     11 enum MyError{ERROR_NO=0,ERROR_SET=1,ERROR_OPERATOR=2,ERROR_ZERO=4,ERROR_STRING=8,ERROR_RANGE=16}; 
     12 
     13 void printError(MyError me){
     14     if(me==ERROR_NO){
     15         cout<<"没有错误";
     16     }
     17     else if(me==ERROR_SET){
     18         cout<<"设置参数非法";
     19     }
     20     else if(me==ERROR_OPERATOR){
     21         cout<<"操作符非法";
     22     }
     23     else if(me==ERROR_ZERO){
     24         cout<<"除0错误";
     25     }
     26     else if(me==ERROR_STRING){
     27         cout<<"算式非法";
     28     }
     29     else if(me==ERROR_RANGE){
     30         cout<<"计算结果超出范围";
     31     }
     32     else{
     33         cout<<"未定义的错误类型";
     34     } 
     35     cout<<"    错误代码:"<<me<<endl<<endl;
     36 }
     37 
     38 class unit                        //后缀表达式用,单元类 
     39 {
     40 public:
     41     char op;
     42     double num;
     43     int kind;
     44     unit(){
     45         kind=0;
     46     }
     47     void set(char c){
     48         op=c;
     49         kind=1;
     50     }
     51     void set(double d){
     52         num=d;
     53         kind=2;
     54     }
     55 };
     56 
     57 class fenshu                        //分数类 
     58 {
     59 public:
     60     int fz;
     61     int fm;
     62     fenshu(int a,int b){
     63         fz=a;fm=b;
     64         yuefen();
     65     }
     66     void yuefen(){
     67         if(fz==0)
     68             return; 
     69         int t;
     70         int a=fz;
     71         int b=fm;
     72         if (a < b) {
     73             t = a;
     74             a = b;
     75             b = t;
     76         }
     77         while (t = a % b) {
     78             a = b;
     79             b = t;
     80         }
     81         if(b!=1){
     82             fz/=b;
     83             fm/=b;
     84         }
     85         if(fm<0){
     86             fz=-fz;
     87             fm=-fm;
     88         }
     89     }
     90     void print(){
     91         cout<<fz<<"/"<<fm;
     92     }
     93     string getfenshu(){
     94         char s[20];
     95         if(fm==1){
     96             sprintf(s,"%d",fz);
     97         } 
     98         else{
     99             sprintf(s,"%d/%d",fz,fm);
    100         } 
    101         string ss=s;
    102         return ss;
    103     }
    104     fenshu operator +(fenshu &fs){
    105         fenshu f(fz*fs.fm+fs.fz*fm,fm*fs.fm);
    106         f.yuefen();
    107         return f;
    108     }
    109     fenshu operator -(fenshu &fs){
    110         fenshu f(fz*fs.fm-fs.fz*fm,fm*fs.fm);
    111         f.yuefen();
    112         return f;
    113     }
    114     fenshu operator *(fenshu &fs){
    115         fenshu f(fz*fs.fz,fs.fm*fm);
    116         f.yuefen();
    117         return f;
    118     }
    119     fenshu operator /(fenshu &fs){
    120         if(fs.fz==0){
    121             fenshu f1(0,1);
    122             return f1;
    123         }
    124         fenshu f(fz*fs.fm,fm*fs.fz);
    125         f.yuefen();
    126         return f;
    127     }
    128     void operator =(fenshu &fs){
    129         fz=fs.fz;
    130         fm=fs.fm;
    131     }
    132     bool operator ==(fenshu &fs){
    133         return fz==fs.fz&&fm==fs.fm;
    134     }
    135 };
    136 
    137 class Calculator                    //核心计算器类 
    138 {
    139 public:
    140     //辅助计算参数 
    141     double result;                    //计算结果 
    142     fenshu fresult;                    //分数计算结果 
    143      MyError Error;                    //计算过程中是否有错误 
    144      string str;                        //存放中缀表达式 
    145      
    146     Calculator(string s):fresult(1,1){            //计算器初始化 
    147         u=new unit;
    148         clear();
    149         str=s;
    150         accuracy=-1; 
    151         maxunit=80;
    152         daterange=100000;
    153     }
    154     
    155     MyError run(){                        //计算表达式的值,存入result
    156         MyError temperror=zzh(str); 
    157         if(temperror!=ERROR_NO){
    158             Error=temperror;
    159             result=-11111;
    160             return Error;
    161         }
    162         int i;
    163         bool b=true;
    164         for(i=0;i<str.size();i++){    //没有小数点,就计算分数结果 
    165             if(str[i]=='.'){
    166                 b=false;
    167                 break;
    168             }
    169             
    170         }
    171         
    172         if(b){
    173             temperror=getFResult();
    174             if(temperror!=ERROR_NO){
    175                 fenshu f(-1,-1);
    176                 fresult=f;
    177                 Error=temperror;
    178                 return Error;
    179             }
    180             else if(abs(fresult.fz)>daterange||abs(fresult.fm)>daterange){
    181                 Error=ERROR_RANGE;
    182                 return Error;
    183             } 
    184         }
    185         else{
    186             temperror=getResult();
    187             if(temperror!=ERROR_NO){
    188                 Error=temperror;
    189                 result=-11111;
    190                 return Error;
    191             }
    192             else if(abs(result)>daterange){
    193                 Error=ERROR_RANGE;
    194                 return Error;
    195             } 
    196         }
    197         return ERROR_NO;
    198     }
    199     
    200     void clear(){                    //清空计算器一切辅助计算参数 
    201         num=0;
    202         Error=ERROR_NO;
    203         result=0;
    204         fenshu f(1,1);
    205         fresult=f; 
    206         str="";
    207         delete u; 
    208         u=new unit[maxunit]; 
    209     }
    210     
    211     void recalculator(string s){    //重启计算器对象 
    212         clear();
    213         str=s;
    214     }
    215         
    216     string getMyResult(){                                //获得计算结果,小数结果或者分数结果 
    217         int i=0;
    218         char s[20];
    219         string ss;
    220         for(;i<str.size();i++){
    221             if(str[i]=='.'){
    222                 if(accuracy!=-1)                            //判断精度并输出 
    223                     sprintf(s,"%.*lf",accuracy,result);
    224                 else
    225                     sprintf(s,"%g",result);
    226                 ss=s;
    227                 return ss; 
    228             }
    229         }
    230         ss=fresult.getfenshu();
    231         return ss;
    232     } 
    233     
    234     MyError setDateRange(int type){                //设置数据范围 
    235         if(0<type){
    236             daterange=type;
    237             return ERROR_NO;
    238         }
    239         else
    240             Error=ERROR_SET;
    241         return ERROR_SET;
    242     } 
    243     
    244     MyError setMaxUnit(int num){                //设置最大识别数量 
    245         if(0<num&&num<=80){
    246             maxunit=num;
    247             u=new unit[maxunit];             //清空后缀表达式 
    248             this->num=0; 
    249             return ERROR_NO;
    250         }
    251         else
    252             Error=ERROR_SET;
    253         return ERROR_SET;
    254     }
    255     
    256     MyError setAccuracy(int a){                    //设置精度 
    257         if(a>=-1&&a<=6){
    258             accuracy=a;
    259             return ERROR_NO;
    260         }
    261         else
    262             Error=ERROR_SET;
    263         return ERROR_SET;
    264     }
    265     
    266 private:
    267     //非辅助计算参数,设置后,除非重复设置,否则不会被clear之类的清除 
    268     int daterange;                    //算式参数中数据的范围 
    269     int maxunit;                    //算式参数最多能识别的字符数量 
    270     int accuracy;                    //小数精确位数,-1为不精确,即去掉所有末尾的0,其他数字即小数点后保留的位数 
    271     
    272     //辅助计算参数 
    273     unit *u;                        //存储后缀表达式 
    274      int num;                        //后缀表达式unit数量 
    275      
    276     MyError zzh(string s){                        //中缀表达式转后缀表达式
    277         if(s.size()>maxunit){ 
    278             return ERROR_STRING;                //error,传入的算式长度超过设置的最大识别数量
    279         } 
    280         char c; 
    281         char *temp1=new char[maxunit];
    282         double temp;
    283         string stemp;
    284         stack<char> st;
    285         while(!s.empty()){                    //如果字符串不为空则继续循环 
    286             c=s[0];
    287             if(isoperator(c)){                //是操作符 
    288                 s.erase(0,1);                //从string中删除操作符  
    289                 if(pushintostack(c,&st)==ERROR_OPERATOR)
    290                     return ERROR_OPERATOR;
    291             }
    292             else if(isnum(c)){                            //是数字 
    293                 stringstream sst(s);
    294                 sst>>temp;
    295                 sprintf(temp1,"%g",temp);
    296                 stemp=temp1;
    297                 s.erase(0,stemp.size());    //从string中删除数字
    298                 sst.clear(); 
    299                 u[num++].set(temp);            //存储数字到栈中 
    300             }
    301             else{
    302                 return ERROR_STRING;
    303             }
    304         } 
    305         if(pushintostack('#',&st)==ERROR_OPERATOR)
    306             return ERROR_OPERATOR;
    307         return ERROR_NO;
    308     }
    309     
    310     bool isoperator(char c){                //判断是否是操作符 
    311         if(c=='+')
    312             return true; 
    313         if(c=='-')
    314             return true; 
    315         if(c=='*')
    316             return true; 
    317         if(c=='/')
    318             return true; 
    319         if(c=='(')
    320             return true; 
    321         if(c==')')
    322             return true;     
    323         return false;
    324     }
    325     
    326     bool isnum(char c){
    327         if(c>='0'&&c<='9')
    328             return true;
    329         return false;
    330     }
    331     
    332     int youxian(char c1,char c2){            //判断两操作符优先级 
    333         if(c2=='#')        //结束符 
    334             return 0;
    335         if(c2=='(')
    336             return 1;
    337         if(c2==')')
    338             if(c1=='(')
    339                 return 2;
    340             else
    341                 return 0;
    342         if(c1=='(')
    343             if(c2=='+'||c2=='-'||c2=='*'||c2=='/')
    344                 return 1;
    345         if(c1=='*'||c1=='/')
    346             return 0;
    347         if(c1=='+'||c1=='-')
    348             if(c2=='*'||c2=='/')
    349                 return 1;
    350             else if(c2=='+'||c2=='-')
    351                 return 0; 
    352         return -1;                            //非法运算符 
    353     }
    354     
    355     MyError pushintostack(char c,stack<char> *st){        //将操作符执行一系列入栈判断操作 
    356         char a;
    357         int y=0;
    358         while(!st->empty()){
    359             a=st->top();
    360             y=youxian(a,c);
    361             if(y==0){                //后来的操作符优先级小 
    362                 st->pop();
    363                 u[num++].set(a);
    364             }
    365             else if(y==1){            //后来的操作符优先级大 
    366                 break;
    367             }
    368             else if(y==2){            //俩操作符是'('和')'
    369                 st->pop();
    370                 return ERROR_NO;
    371             }
    372             else
    373                 return ERROR_OPERATOR;
    374         }
    375         st->push(c);
    376         return ERROR_NO;
    377     }
    378     
    379     void test(){                                    //输出后缀表达式,测试用(暂留) 
    380         int i;
    381         cout<<num<<endl;
    382         for(i=0;i<num;i++){
    383             if(u[i].kind==1)
    384                 cout<<u[i].op<<" ";
    385             else if(u[i].kind==2)
    386                 cout<<u[i].num<<" ";
    387         }
    388     }
    389     
    390     MyError getResult(){                        //由run函数调用,获取小数结果,存入result中 
    391         int i;
    392         char op;
    393         double num1,num2;
    394         stack<double> st;
    395         for(i=0;i<num;i++){                    //处理后缀表达式 
    396             if(u[i].kind==2){                //如果是数字则入栈 
    397                 st.push(u[i].num);
    398             }
    399             else if(u[i].kind==1){            //如果是操作符,则出栈两个数字 
    400                 op=u[i].op;
    401                 if(st.empty()) 
    402                     return ERROR_STRING;    //算式非法
    403                 num2=st.top();
    404                 st.pop();
    405                 if(st.empty())                 
    406                     return ERROR_STRING;    //算式非法
    407                 num1=st.top();
    408                 st.pop();
    409                 switch(op){
    410                 case '+':
    411                     st.push(num1+num2);
    412                     break;
    413                 case '-':
    414                     st.push(num1-num2);
    415                     break;
    416                 case '*':
    417                     st.push(num1*num2);
    418                     break;
    419                 case '/':
    420                     if(num2==0)             
    421                         return ERROR_ZERO;    //除0错误
    422                     st.push(num1/num2);
    423                     break;
    424                 } 
    425             }
    426             else                 
    427                 return ERROR_STRING;        //算式非法
    428         }
    429         result=st.top();
    430         return ERROR_NO;
    431     } 
    432     
    433     MyError getFResult(){                        //由run函数调用,获取分数结果,存入fresult中 
    434         int i;
    435         char op;
    436         fenshu f1(1,1),f2(1,1);
    437         stack<fenshu> st; 
    438         for(i=0;i<num;i++){
    439             if(u[i].kind==2){                //如果是数字则入栈 
    440                 st.push(fenshu(u[i].num,1));
    441             }
    442             else if(u[i].kind==1){            //如果是操作符,则出栈两个数字 
    443                 op=u[i].op;
    444                 if(st.empty())                 
    445                     return ERROR_STRING;    //算式非法
    446                 f2=st.top();
    447                 st.pop();
    448                 if(st.empty())                 
    449                     return ERROR_STRING;    //算式非法
    450                 f1=st.top();
    451                 st.pop();
    452                 switch(op){
    453                 case '+':
    454                     st.push(f1+f2);
    455                     break;
    456                 case '-':
    457                     st.push(f1-f2);
    458                     break;
    459                 case '*':
    460                     st.push(f1*f2);
    461                     break;
    462                 case '/':
    463                     if(f2.fz==0)            
    464                         return ERROR_ZERO;    //除0错误 
    465                     st.push(f1/f2);
    466                     break;
    467                 } 
    468             }
    469             else                 
    470                 return ERROR_STRING;        //算式非法
    471         }
    472         fresult=st.top();
    473         return ERROR_NO;
    474     } 
    475     
    476 }; 
    477 
    478 int main(int argc, char** argv) {
    479     ifstream in("equation.txt");                //打开算式所在文件 
    480     Calculator cal("1+1");                        //创建计算器类 
    481     string s;
    482     string answer;
    483     int i=0,j;
    484     bool b;
    485     int zq=0,cw=0; 
    486     MyError temperror;
    487     if(!in){
    488         cout<<"打开文件出错"<<endl;
    489         return -1;
    490     }
    491     while(in>>s){
    492         b=true;
    493         cal.recalculator(s);                    //重启计算器,并传入算式参数                 
    494         cout<<""<<++i<<"题:"<<endl;            //在屏幕上打印题号     
    495         temperror=cal.run();                    //让计算器计算结果
    496         if(temperror!=ERROR_NO){                //算式非法 
    497             printError(temperror);
    498             continue;
    499         }
    500         cout<<s<<"=";                            //在屏幕上打印题目 
    501         cin>>answer;                            //获得用户输入的结果 
    502         if(answer==cal.getMyResult())            //判断正误 
    503                 b=true;
    504             else
    505                 b=false; 
    506         if(b){                                    //判断正误后输出交互结果 
    507             cout<<"答案正确"<<endl; 
    508             zq++;
    509         }
    510         else{
    511             cout<<"答案错误"<<endl;
    512             cout<<"正确答案是:"<<cal.getMyResult()<<endl;
    513             cw++;
    514         }
    515         cout<<endl;
    516     }
    517     cout<<"总共"<<zq+cw<<"道题,答对"<<zq<<"道,答错"<<cw<<"";                 //最后输出此次作业的结果 
    518     in.close();
    519     return 0;
    520 }
    ALL Code
  • 相关阅读:
    cms模板内的标签替换思路(不可能比这更优秀的了)
    Mysql数据不算大,备份却非常慢
    PHP防止盗链
    Flash+PHP多文件上传,可将PHP换成别的语言脚本,如asp;jsp等
    把Linux Ubuntu安装到U盘上
    PHP中功能强大却少使用的函数 为你提供更多的思路
    云端計算詳解
    PHP循环输出变量
    HipHop
    80后传记
  • 原文地址:https://www.cnblogs.com/chengyu404/p/5322739.html
Copyright © 2020-2023  润新知