结对开发-1


一、    设计思路:


程序包含两部分,一部分是算式的生成,一部分是栈的使用用来判断和计算结果;


算式生成,用的是调用子函数,因为每一个年级的出题要求不同所以对出题的范围加了条件限制;程序的结构框架大致为:


程序开始将字符串数组宏定义,出题的数量和选择打印的方式都进行宏定义;


            For(         )


          {


                For(      )


                {


                    a> 产生左括号;(用switch…..case语句来判断;)


                     b> 产生数字:(其中,可以有分数小数和整数的产生)


                       其中不同年级选择的范围不同;


                    c>产生右括号;(右括号的产生是用左括号的数量来限制的)


                    d>产生运算符;运算符在输出最后一位数字之后就不会执行运算符产生的程序;)


}


}


栈程序中:


将算式生成的string类型的数组,转化为char类型的,读入到栈中,然后利用字符串优先级的判断,计算函数,我们的程序中不能出现负数所以在输出结果时加了结果判断;

  1 //组成员:禹慧慧 吕兰兰
  2 //四则运算,在前面的基础上实现判断正误  2016.3.19
  3 //我们的结果是如果选择dos界面,可以在界面上实现输入结果、判断正误与给出答案;如果选择txt,则打印出一份题目和一份答案
  4 //没有控制余数,都算成了小数
  5 #include<iostream>
  6 #include<ctime>
  7 #include<cmath>
  8 #include<sstream>
  9 #include<string>
 10 #include<fstream>
 11 #include<iomanip>
 12 #define MAX 1000
 13 using namespace std;
 14 
 15 int N;
 16 int way;
 17 string str[1000];
 18 ofstream outfile("questions.txt");
 19 ofstream outfile_1("answers.txt");
 20 
 21 
 22 class Input
 23 {
 24 public:
 25     Input()
 26     {
 27         for( int i = 0;i < MAX;i++ )
 28             Str_input[i] = '';
 29     }
 30     char Str_input[MAX];
 31     void inStr(string str11)
 32     {
 33         strcpy(Str_input,str11.c_str());
 34     }
 35 };
 36 
 37 /*输出模块*/
 38 class Output
 39 {
 40 public:
 41     Output()
 42     {
 43         result = 0;
 44     }
 45     void getRes( double res )
 46     {
 47         result = res;
 48     }
 49     void printRes(double &num_an)
 50     {
 51         num_an=result;
 52     }
 53 private:
 54     double result;
 55 };
 56 
 57 /*计算用的存储结构*/
 58 template <class Type>
 59 class STACK{                 
 60 private:
 61     Type base[MAX];
 62     int Size;
 63 public:
 64     STACK()
 65     {
 66         Size=0;
 67     };
 68     void push(Type a)     
 69     {
 70         base[Size]=a;
 71         Size++;
 72     }
 73     Type pop()           
 74     {
 75         return base[--Size];
 76     }
 77     int size()
 78     {return Size;}
 79 };
 80 
 81 
 82 /*计算的模块*/
 83 class jisuan
 84 {
 85 public: 
 86     bool shuhanshu(char);                 
 87     bool fuhanshu(char);                 
 88     int jckh(char);                  
 89     bool jcxsd(char *);              
 90     int pdyxj(char);                 
 91     double ToData(char*);             
 92     double Call(double,double,char);    
 93     int ppkh(char* buffer,int pos); 
 94     void Opr( STACK<char>&, STACK<double>&, int& ); 
 95     double Calculate(char*, double& );   
 96 
 97 };
 98 bool jisuan::shuhanshu(char ch)      
 99 {
100     return ((ch>='0'&&ch<='9')||ch=='.')?true:false;
101 }
102 bool jisuan::fuhanshu(char ch)     
103 {
104     return (ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='#')?true:false;
105 }
106 int jisuan::jckh(char ch)
107 {
108     if(ch=='(')
109         return 1;
110     if(ch==')')
111         return -1;
112     return 0;
113 }
114 bool jisuan::jcxsd(char *ch)
115 {
116     int a=0;
117     for(int i=0;i<strlen(ch);i++)
118         if(ch[i]=='.')          
119             a++;
120     if(a>1)
121         return false;
122     return true;
123 }
124 int jisuan::pdyxj(char ch)          //符号的优先极别
125 {
126     switch(ch)
127     {
128     case '+':
129         return 0;
130     case '-':
131         return 0;
132     case '*':
133         return 1;
134     case '/':
135         return 1;
136     case '#':
137         return 0;
138     default:
139         return -1;
140     }
141 }
142 double jisuan::ToData(char* ch)   //将数字转化为数值
143 {
144     int i,j,sumn=0;
145     double sum=0.0;
146     if(!jcxsd(ch)) return 0.0;
147     for(i=0;i<strlen(ch);i++)           
148     {
149         if(ch[i]!='.')
150             sumn=sumn*10+(ch[i]-'0');
151         else break;
152     }
153     if(i<strlen(ch))
154         for(j=i+1;j<strlen(ch);j++)        
155             sum=sum*10+(ch[j]-'0');
156     sum /= pow(10.0,(double)(strlen(ch)-1-i));
157     return (sum+sumn);                    
158 }
159 double jisuan::Call(double sum,double data,char ch)
160 {
161     double ans=0.0;
162     switch(ch)
163     {
164     case '+':
165         ans=sum+data;
166         break;
167     case '-':
168         ans=sum-data;
169         break;
170     case '*':
171         ans=sum*data;
172         break;
173     case '/':
174         if( data != 0.0 )
175             ans=sum/data;
176         else
177         {
178             cout<<"程序出现除0错误,终止!
";
179             system("pause");
180             exit(1);
181         }
182         break;
183     case '#':
184         return 0;
185     default:ans=0.0;
186         break;
187     }
188     return ans;
189 }
190 int jisuan::ppkh(char* buffer,int pos)     //利用栈找到匹配的括号
191 {
192     STACK<char> Temp;
193     int i;
194     for(i=pos;i<strlen(buffer);i++)
195     {
196         if(jckh(buffer[i])==1)
197             Temp.push('0');
198         if(jckh(buffer[i])==-1)
199         {
200             Temp.pop();
201             if(Temp.size()==0) return i;
202         }
203     }
204     return -1;
205 }
206 void jisuan::Opr(STACK<char>& symbol,STACK<double>& data,int& mark)
207 {
208     double sum;
209     while(symbol.size()!=0)
210     {
211         char tem=symbol.pop();
212         int temp=pdyxj(tem);
213         symbol.push(tem);
214         if(temp<mark)
215             break;
216         else{
217             sum=Call(data.pop(),data.pop(),symbol.pop());
218             data.push(sum);
219         }
220     }
221 }
222 double jisuan::Calculate(char* buffer,double& sum)   //字符串读入和各个函数调配
223 {
224     STACK<double> data;
225     STACK<char> symbol;
226     double ans;
227     char temp[MAX];
228     int ct=0,mark=0,tp=0;
229     data.push(sum);
230     while(ct<=strlen(buffer))
231     {
232         if(shuhanshu(buffer[ct]))            //如果是数字或小数点
233         {
234             while( ct < strlen(buffer) && shuhanshu(buffer[ct]) )
235                 temp[tp++]=buffer[ct++];
236             temp[tp]='';
237             tp=0;                         //读到非数字也非小数为止
238             ans=ToData(temp);             //把读到的字符串转化为数
239             data.push(ans);
240 
241             if(ct==strlen(buffer))        //已经独到字符串末尾
242             {
243                 mark=0;
244                 Opr(symbol,data,mark);    
245                 sum=data.pop();           
246                 return sum;               
247             }
248             else{
249                 int mark=pdyxj(buffer[ct]);
250                 Opr(symbol,data,mark);     //计算
251             }
252         }
253         else if(fuhanshu(buffer[ct]))         //如果是运算符
254             symbol.push(buffer[ct++]);     //运算符入symbol栈
255         else
256         {
257             char BF[100];int k=0;          //如果都不是,则只能是括号
258             while( jckh( buffer[ct] ) != 1 && ct <= strlen(buffer) )
259                 BF[k++] = buffer[ct++];
260             BF[k]='';
261             if(jckh(buffer[ct])==1)       //一旦读到左括号,寻找它匹配的右括号
262             {
263                 int i,j;
264                 char Temp[100];
265                 for(i=ct+1,j=0;i<ppkh(buffer,ct);i++,j++)
266                     Temp[j]=buffer[i];     //把这对括号中的字符串存入Temp
267                 Temp[j]='';
268                 data.push(Calculate(Temp,sum)); 
269 
270                 ct+=(strlen(Temp)+1);       
271                 if(ct+1==strlen(buffer))   
272                 {
273                     mark=0;
274                     Opr(symbol,data,mark);
275                     sum=data.pop();
276                     return sum;
277                 }
278                 else
279                 {
280                     mark=pdyxj(buffer[ct+1]); //不是的话继续计算
281                     Opr(symbol,data,mark);
282                 }
283                 ct++;                           //读入下一个字符
284             }
285         }
286     }
287     return 0.;
288 }
289 int Expression(int grade,int N)
290 {
291 
292     Input in;
293     jisuan cl;
294     Output out;
295     double sum=0.0;
296     double result;
297     double answer;
298     cout.precision(5);
299     int random_a,random_b,random_c,random_e,random_f,random_g;
300     int max,min;//整数
301     int random_d;
302     double random_h;
303     
304     //根据年级的不同选择每道题目的数的数量
305     if(grade==2)
306     {
307         random_a=rand()%2+2;
308         max=100;
309         min=1;
310     }
311     if(grade==3)
312     {
313         random_a=rand()%3+2;
314         max=500;
315         min=1;
316     }
317     if(grade==4)
318     {
319         random_a=rand()%3+2;
320         max=1000;
321         min=1;
322     }
323     if(grade==5)
324     {
325         random_a=rand()%3+2;
326         max=10000;
327         min=1;
328     }
329     if(grade==6)
330     {
331         random_a=rand()%3+2;
332         max=10000;
333         min=1;
334     }
335     for(int j=0;j<N;j++)
336     { 
337         int flag=0;
338         int count_p=0,count_q=0;//计算括号的数量
339         for(int i=0;i<random_a;i++)
340        {
341           if(grade==2||grade==3||grade==4)
342             {
343                 random_b=0;//只有整数计算
344             }
345          if(grade==5||grade==6)
346             {
347                 random_b=rand()%3+0;
348             }
349         char str1[100];
350         if(random_a>2&&i<(random_a-1))
351         {
352               random_d=rand()%4+0;
353               switch(random_d)//控制括号的产生
354               {
355                 case 0:flag=0;break;
356                 case 1:if(i!=(random_a-1)&&i<(random_a-2)){str[j]+='(';flag=1;count_q+=1;}break;
357                 case 2:flag=0;break;
358                 case 3:if(i!=(random_a-1)&&i<(random_a-2)){str[j]+='(';flag=1;count_q+=1;}break;
359                 }
360           }
361             //数字的产生
362             switch(random_b)
363             {
364                 
365             case 0:
366                 {
367                     random_c=rand()%(max-min+1)+min;//整数
368                     itoa(random_c,str1,10);
369                     str[j]+=str1;
370                    } break;
371                    
372             case 1:
373                 {
374                        random_h=(rand()%100)/100.0;//小数
375                        random_e=rand()%10+0;
376                        random_h+=random_e;
377                        stringstream ss;
378                        ss<<random_h;
379                        str[j]+=ss.str();
380                    }
381                    break;
382             case 2:
383                  {//分数
384                 do{
385                     random_f=rand()%20+1;
386                     random_g=rand()%10+1;
387                    }while(random_g==random_f);
388                 int number=1;
389                 int m;
390                 if(random_g>random_f)
391                 {    
392                      m=random_f;
393                 }
394                 else 
395                 { m=random_g;}
396                 for(int k=2;k<m+1;k++)
397                 {
398                      if((random_g%k==0)&&(random_f%k==0))
399                     {
400                          number=k;
401                     } 
402                 }
403                 random_f=random_f/number;
404                 random_g=random_g/number;
405                 str[j]+='(';
406                 if(random_g==1)
407                 {
408                      int n=0;
409                      n=random_g;
410                      random_g=random_f;
411                      random_f=n;
412                 }
413                 itoa(random_f,str1,10);
414                 str[j]+=str1;
415                 str[j]+='/';
416                 itoa(random_g,str1,10);
417                 str[j]+=str1;
418                 str[j]+=')';
419                }break;
420             }
421             //右括号的产生
422            if((flag!=1)&&(count_p!=count_q))
423            {
424                str[j]+=')';
425                count_p+=1;
426            }
427            if(i==(random_a-1))
428            {
429                if(count_p<count_q)
430                {
431                    for(int k=0;k<(count_q-count_p);k++)
432                    str[j]+=')';
433                }
434             }
435         if(i!=(random_a-1))
436         {
437             random_b=rand()%4+0;
438             switch(random_b)
439             {
440             case 0:{str[j]+='+';}break;
441             case 1:{str[j]+='-';}break;
442             case 2:{str[j]+='*';}break;
443             case 3:{str[j]+='/';}break;
444             }
445         }
446      }    
447        
448        in.inStr(str[j]);                              //输入模块
449        out.getRes( cl.Calculate(in.Str_input,sum) ); //计算模块
450        out.printRes(result);
451        if (result<0)
452        {
453            str[j]="";
454            j--;
455            
456        } 
457        else
458        {
459            
460            if(way==1)
461            {
462            cout<<str[j]<<"="<<endl;
463            cout<<"请输入答案(6位有效数字):";
464            cin>>answer;
465          
466            if (answer==result)
467            {
468 
469                cout<<"回答正确!"<<endl;
470            }
471            else
472            {
473                cout<<"回答错误!"<<endl;
474                cout<<"正确结果为:"<<result<<endl;
475            }
476            }
477            else
478            {
479                outfile<<str[j]<<"=";
480                outfile<<endl;
481                outfile_1<<"正确结果为:"/*<<setprecision(5)*/<<result;
482                outfile_1<<endl;
483            }
484        }
485             
486     }
487     
488     return 0;
489 }    
490 
491 
492     int main()
493 {
494     int grade;
495     srand(time(0));
496     
497     cout<<"********************************************************************************"<<endl;
498     cout<<"***************************欢迎使用小学四则运算出题系统*************************"<<endl;
499     cout<<"********************************************************************************"<<endl;
500     cout<<"*******作者:石家庄铁道大学   信1301-2     禹慧慧    吕兰兰    2016.3.19 *******"<<endl;
501     cout<<"********************************************************************************"<<endl;
502     cout<<"请选择打印方式:(0-TXT,1-DOS):";
503     cin>>way;
504     cout<<"********************************请选择年级**************************************"<<endl;
505     cout<<"                                   2年级                                        "<<endl;
506     cout<<"                                   3年级                                        "<<endl;
507     cout<<"                                   4年级                                        "<<endl;
508     cout<<"                                   5年级                                        "<<endl;
509     cout<<"                                   6年级                                        "<<endl;
510     cout<<"********************************************************************************"<<endl;
511     cin>>grade;
512         
513     cout<<"请输入题目数量:";
514     cin>>N;
515     if(grade==2)
516     {
517     Expression(grade,N);
518     }
519     if(grade==3)
520     {
521         Expression(grade,N);
522     }
523     if(grade==4)
524     {
525         Expression(grade,N);
526     }
527     if(grade==5)
528     {
529         Expression(grade,N);
530     }
531     if(grade==6)
532     {
533         Expression(grade,N);
534     }
535     outfile.close();
536     outfile_1.close();
537  }
    
三、    用时:计划花费20个小时,实际花费了23个小时;其中包括改错调试程序;
四、    体会:本次试验又使用了新的知识;子函数的调用和栈的使用以及优先级的判断,这次实验花费的时间很长并且上网和查书找了很多东西。输入输出流的使用,以及栈的优先级的判            断,出栈入栈,计算结果,判断是否有错等。这次实验很有成就感!!!O(∩_∩)O~~
五、程序运行截图:
工作照:

项目计划日志(单位:h):

听课

编写程序

阅读相关书籍

网上查找资料

日总计

周一

2

0

1

0

3

周二

0

3

0.5

3.5

周三

0

3

1

0

4

周四

2

6

1

9

周五

0

4

1

1

6

周六

0

3

1

4

周日

周总计

4

19

3

      3.5

29.5

时间记录日志:(单位:min):

日期

开始时间

结束时间

中断时间

净时间

活动

备注

星期一

14:00

15:50

10

100

听课

软件工程

20:00

21:00

0

60

看书

构建之法

星期二

19:00

19:30

0

30

网上查找资料

20:00

23:00

0

180

编程

结对编程

星期三

15:00

22:00

180

240

编程和上网查找资料并且调试程序

结对编程

星期四

14:00

15:50

10

100

听课

软件工程

16:00

23:00

60

360

编程

结对编程

星期五

16:00

21:00

60

240

编程上网查找资料

结对编程

21:30

22:30

0

60

看书

构建之法

星期六

19:00

22:00

0

180

编程和写博客

结对编程

缺陷记录日志:

日期

编号

类型

引入阶段

排除阶段

修复时间

修复缺陷

3/17

1

20

编码

调试

20:00

括号输出错误,运算不正确

3/18

2

20

编码

调试

19:00-21:00

对栈的编写和运算结果

3/19

3

20

编码

调试

20:00-22:00

括号的丢失和语法的错误。

 

组员禹慧慧网址:http://www.cnblogs.com/yhhzxcvbnm/

原文地址:https://www.cnblogs.com/lvlan/p/5296574.html