结对编程项目阶段性进展

第一阶段目标 - 能把计算的功能封装起来,通过测试程序和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

 

posted @ 2016-03-26 13:21  13070035王辰成  阅读(233)  评论(0编辑  收藏  举报