第一周作业——小学四则运算题

作业要求:

  写一个能自动生成小学四则运算题目的命令行 “软件”, 分别满足下面的各种需求,这些需求都可以用命令行参数的形式来指定:

    a) 支持整数、真分数的四则运算。例如:  1/6 + 1/8 = 7/24

    b) 逐步扩展功能和可以支持的表达式类型,最后希望能支持下面类型的题目(最多 10 个运算符,括号的数量不限制)  

      25 - 3 * 4 - 2 / 2 + 89 = ?
         1/2 + 1/3 - 1/4 = ? 
         ( 5 - 4 ) * ( 3 +28 ) =?

设计思路:

  采用使用栈将表达式中缀转后缀的做法,求解表达式的值

     对于小数型,采取double型的栈存取,其余做法与一般方法一致

     对于分数型,采取字符串的形式进行存取

     对于分数型,重载了+,-,*的运算规则,使其满足分数加减乘法的要求。其函数中包含了大量的字符串分割,字符串转整型等操作,最后返回一个结果的字符串

 

已经实现功能:

  1. 随机生成整数数或者分数算式,整数算式结果为小数,分数算式结果为真分数
  2. 真分数的四则运算,结果为真分数
  3. 支持括号
  1 #include <iostream> 
  2 #include <stdlib.h>
  3 #include <time.h>
  4 #include <stack>
  5 #include <math.h>
  6 #include <string.h>
  7 #include <iomanip>
  8 
  9 using namespace std;
 10 
 11 char basic_op_de[4]={'+','-','*','/'};
 12 
 13 unsigned char Prior_de[8][8] ={         // 运算符优先级表 
 14              // '+' '-' '*' '/' '(' ')' '#' '^' 
 15          /*+*/'>','>','<','<','<','>','>','<', 
 16          /*-*/'>','>','<','<','<','>','>','<', 
 17          /***/'>','>','>','>','<','>','>','<', 
 18          /*/*/'>','>','>','>','<','>','>','<',
 19          /*(*/'<','<','<','<','<','=',' ','<',
 20          /*)*/'>','>','>','>',' ','>','>','>',
 21          /*#*/'<','<','<','<','<',' ','=','<',
 22          /*^*/'>','>','>','>','<','>','>',' ',
 23 };
 24 
 25 char graph_de[8]={'+','-','*','/','(',')','#','^'};
 26 
 27 
 28 bool In_de(char a,char b[7])       { //判断是否为运算符
 29     int i;
 30     bool c=false;
 31     for(i=0;i<=7;i++)
 32     {
 33         if(a==b[i])
 34         c=true;
 35     }
 36     return c;
 37 }
 38 
 39 char  Precede_de(char a,char b)     {//判断优先级
 40     int i,j;
 41     if(a=='+') i=0;
 42     if(a=='-') i=1;
 43     if(a=='*') i=2;
 44     if(a=='/') i=3;
 45     if(a=='(') i=4;
 46     if(a==')') i=5;
 47     if(a=='#') i=6;
 48     if(a=='^') i=7;
 49     if(b=='+') j=0;
 50     if(b=='-') j=1;
 51     if(b=='*') j=2;
 52     if(b=='/') j=3;
 53     if(b=='(') j=4;
 54     if(b==')') j=5;
 55     if(b=='#') j=6;
 56     if(b=='^') j=7;
 57     return Prior_de[i][j];
 58 }
 59 
 60 double Operate_de(double Num1,char b,double Num2)     {//进行运算
 61     double result=1;
 62     switch(b){
 63         case'+':return Num1+Num2;break;
 64         case'-':return Num1-Num2;break;
 65         case'*':return Num1*Num2;break;
 66         case'/':return Num1/Num2;break;
 67     }
 68 } 
 69 
 70 double EvaluateExpression_de(char* string)            //求表达式的值 
 71 {
 72     int count=0;
 73     stack<double> p1;       //运算数 
 74     stack<char> p2;
 75     stack<double> *S1;              
 76     stack<char> *S2;     //运算符 
 77     S1=&p1;
 78     S2=&p2;
 79     char temp,y,x,c,cpre='('; //prec用与记录前一个字符 
 80     double Num1,Num2,num; 
 81     char str[50];
 82     str[0]='\0';
 83     int i=0;
 84     
 85 
 86     temp='#';
 87     S2->push(temp);
 88     
 89     c=string[count];
 90     count++;
 91     
 92     while(c!='#'||S2->top()!='#'){
 93         if(!In_de(c,graph_de)||c=='.') {    //是运算数 (含小数点)
 94             str[i]=c;
 95             i++;
 96             cpre=c;
 97             c=string[count];
 98             count++;
 99             if(In_de(c,graph_de)){    //不是运算数了,则把字符串转化为数字后压栈 
100                 str[i]='\0';
101                 num=atof(str);
102                 S1->push(num); 
103                 i=0;                 //字符串初始化 
104                 str[i]='\0';
105             }
106         }
107         else{
108                 if(cpre=='('&&c=='-'){
109                     S1->push(0);    
110                 }
111                 switch(Precede_de(S2->top(),c)){
112                     case'<':
113                         S2->push(c);                //进栈 
114                         cpre=c;
115                         c=string[count];
116                         count++;
117                         break;
118                     case'=':
119                         x=S2->top();
120                         S2->pop();
121                         cpre=c;
122                         c=string[count];
123                         count++;
124                         break;
125                     case'>':
126                         y=S2->top();
127                         S2->pop();
128                         Num2=S1->top();
129                         S1->pop();
130                         Num1=S1->top();
131                         S1->pop();
132                     S1->push(Operate_de(Num1,y,Num2));break;        //进栈 
133                 }        
134         }
135     }
136     Num1=S1->top();
137     S1->pop();
138     return Num1;
139 }
140 
141 char basic_op[3]={'+','-','*'};
142 
143  
144 unsigned char Prior[6][6] ={         // 运算符优先级表 
145              // '+' '-' '*' '(' ')' '#'  
146          /*+*/'>','>','<','<','>','>',
147          /*-*/'>','>','<','<','>','>',
148          /***/'>','>','>','<','>','>',
149          /*(*/'<','<','<','<','=',' ',
150          /*)*/'>','>','>','>','>','>',
151          /*#*/'<','<','<','<',' ','=',
152 };
153 
154 char graph[6]={'+','-','*','(',')','#'};
155 
156 bool In(char a,char b[6]) {       //判断是否为运算符
157     int i;
158     bool c=false;
159     for(i=0;i<=5;i++)
160     {
161         if(a==b[i])
162         c=true;
163     }
164     return c;
165 }
166 
167 char  Precede(char a,char b) { //判断优先级
168     int i,j;
169     if(a=='+') i=0;
170     if(a=='-') i=1;
171     if(a=='*') i=2;
172     if(a=='(') i=3;
173     if(a==')') i=4;
174     if(a=='#') i=5;
175     if(b=='+') j=0;
176     if(b=='-') j=1;
177     if(b=='*') j=2;
178     if(b=='(') j=3;
179     if(b==')') j=4;
180     if(b=='#') j=5;
181     return Prior[i][j];
182 }
183 int HCF(int n,int m)    {//最大公约数
184      int p,r,temp;
185      if (n<m) {
186         temp=n;
187         n=m;
188         m=temp;                //把大数放在n中, 小数放在m中
189      }
190      p=n*m;                     //先将n和m的乘积保存在p中, 以便求最小公倍数时用
191      while (m!=0){               //求n和m的最大公约数
192          r=n%m;
193          n=m;
194          m=r;
195      }
196     return n;
197 }
198 
199 int LCD(int n,int m) {  //最小公倍数 
200      int p,r,temp;
201      if (n<m){
202        temp=n;
203        n=m;
204        m=temp;                //把大数放在n中, 小数放在m中
205      }
206      p=n*m;                     //先将n和m的乘积保存在p中, 以便求最小公倍数时用
207      while (m!=0)               //求n和m的最大公约数
208     {r=n%m;
209      n=m;
210      m=r;
211      }
212     return p/n;
213 }
214 char *yuefen(int l,int r) {        //约分 
215     char  *left=(char*)malloc(sizeof(char)*200);
216     char  *right=(char*)malloc(sizeof(char)*200);
217     char  *temp_result2=(char*)malloc(sizeof(char)*1000);
218     if(HCF(l,r)!=1){//不互质
219         int k=HCF(l,r);
220         l=l/k;
221         r=r/k;
222     }
223     itoa(l,left,10);
224     itoa(r,right,10);
225     strcpy(temp_result2,left);
226     strcat(temp_result2,"/");
227     strcat(temp_result2,right);
228 
229     
230     return temp_result2;
231 } 
232 
233 char * Operate(char* Num1,char b,char* Num2){ //进行运算
234     int num1_l,num1_r,num2_l,num2_r,num3_l,num3_r;
235     char *Num1_left=(char*)malloc(sizeof(char)*200);
236     char *Num1_right=(char*)malloc(sizeof(char)*200);
237     char *Num2_left=(char*)malloc(sizeof(char)*200);
238     char *Num2_right=(char*)malloc(sizeof(char)*200);
239     char  *temp_result1=(char*)malloc(sizeof(char)*1000);
240     
241     int i=0,j;                            //分割字符串为4个数 
242     for(i=0;Num1[i]!='/';i++){
243         Num1_left[i]=Num1[i];
244     } 
245     Num1_left[i]='\0';
246     j=i;
247     for(i=0;;i++){
248         Num1_right[i]=Num1[i+j+1];
249         if(Num1_right[i]=='\0')   
250           break;
251     } 
252     for(i=0;Num2[i]!='/';i++){
253         Num2_left[i]=Num2[i];
254     } 
255     Num2_left[i]='\0';
256     j=i;
257     for(i=0;;i++){
258         Num2_right[i]=Num2[i+j+1];
259         if(Num2_right[i]=='\0')   
260         break;
261     } 
262     
263     num1_l=atoi(Num1_left);        //字符串转整型数字 
264     num1_r=atoi(Num1_right);
265     num2_l=atoi(Num2_left);
266     num2_r=atoi(Num2_right);
267     
268     switch(b){
269       case'+': 
270             if(num1_r==num2_r){  //同分母
271                 num1_l=num1_l+num2_l;    
272                 strcpy(temp_result1,yuefen(num1_l,num1_r));
273             } 
274             else{            //分母不同
275                 num3_r=LCD(num1_r,num2_r);  //通分后的分母
276                 num1_l=num1_l*num3_r/num1_r;
277                 num2_l=num2_l*num3_r/num2_r;
278                 num3_l=num1_l+num2_l;      //通分之后的分子
279                 strcpy(temp_result1,yuefen(num3_l,num3_r));
280             } 
281              break;
282 
283       case'-':
284             if(num1_r==num2_r){  //同分母
285                 num1_l=num1_l-num2_l;
286                 strcpy(temp_result1,yuefen(num1_l,num1_r));
287             } 
288             else{           //分母不同
289                 num3_r=LCD(num1_r,num2_r);  //通分后的分母
290                 num1_l=num1_l*num3_r/num1_r;
291                 num2_l=num2_l*num3_r/num2_r;
292                 num3_l=num1_l-num2_l;      //通分之后的分子
293                 strcpy(temp_result1,yuefen(num3_l,num3_r));
294             } 
295             break;
296       case'*':
297             num3_r=num1_r*num2_r;
298             num3_l=num1_l*num2_l;
299             strcpy(temp_result1,yuefen(num3_l,num3_r)); 
300             break;
301     }
302 
303     return temp_result1;
304 } 
305 
306 char* EvaluateExpression(char* string){            //求表达式的值 
307     int str_counter;
308     char **str= (char**)malloc(sizeof(char*)*20);        //存储运算数的字符串载体 
309       for(str_counter=0; str_counter<20; str_counter++)   {
310         str[str_counter] = (char*)malloc(sizeof(char)*200);
311         str[str_counter][0]='\0';                              //初始化 
312       }    
313     str_counter=0;
314     
315     int temp_result_counter;
316     char ** temp_result=(char**)malloc(sizeof(char)*20);      //作为中间运算结果的载体 
317     for(temp_result_counter=0; temp_result_counter<20; temp_result_counter++) {
318         temp_result[temp_result_counter] = (char*)malloc(sizeof(char)*1000);
319         temp_result[temp_result_counter][0]='\0';                              //初始化 
320       }    
321     temp_result_counter=0;
322     
323     int count=0;
324     stack<char *> p1;       //运算数 
325     stack<char> p2;
326     stack<char *> *S1;              
327     stack<char> *S2;     //运算符 
328     S1=&p1;
329     S2=&p2;
330     char temp,y,x,c,cpre='(';                    //cpre用于记录前一个字符 
331     char * Num1=(char*)malloc(sizeof(char)*200);
332     char * Num2=(char*)malloc(sizeof(char)*200); 
333 
334     int i=0;
335     
336     temp='#';
337     S2->push(temp);
338     
339     c=string[count];
340     count++;
341     
342     while(c!='#'||S2->top()!='#'){
343         if(!In(c,graph))                      //是运算数 (含小数点)
344         {
345             str[str_counter][i]=c;
346             i++;
347             cpre=c;
348             c=string[count];
349             count++;
350             if(In(c,graph)){              //不是运算数了,则把字符串转化为数字后压栈 
351                 str[str_counter][i]='\0';
352                 S1->push(str[str_counter]);        //压栈的不是内容,是地址 
353                 str_counter++;
354                 i=0;
355             }
356         }
357         else{                              //运算符 
358             
359             switch(Precede(S2->top(),c)){
360                     case'<':
361                         S2->push(c);                //进栈 
362                         cpre=c;
363                         c=string[count];
364                         count++;
365                         break;
366                     case'=':
367                         x=S2->top();
368                         S2->pop();
369                         cpre=c;
370                         c=string[count];
371                         count++;
372                         break;
373                     case'>':
374                         y=S2->top();
375                         S2->pop();
376                         strcpy(Num2,S1->top());
377                         S1->pop();
378                         strcpy(Num1,S1->top());
379                         S1->pop();
380                         strcpy(temp_result[temp_result_counter],Operate(Num1,y,Num2));          //修改中间结果 
381                         S1->push(temp_result[temp_result_counter]);
382                         temp_result_counter++;
383                         break;        
384             }        
385         }
386     }
387     strcpy(Num1,S1->top());
388     S1->pop();
389     return Num1;    
390 }
391 
392 
393 int main()
394 {
395     int swi;
396     cout<<"-----------欢迎使用小学生计算器---------\n"<<endl;
397     cout<<"--------------输入1;小数计算---------\n"<<endl;
398     cout<<"--------------输入2;分数计算---------\n"<<endl;
399     cout<<"--------------输入0;退出---------\n"<<endl;
400     
401     cout<<"你的选择:";
402     cin>>swi;
403     if(swi==0)  return 0; 
404     else if(swi==1){
405         int count ,left ,right ,op_num,LR,temp;
406     double result;
407     double stu_answer;
408     
409     char *op=(char *)malloc(sizeof(char)*3); 
410     char *left_string=(char *)malloc(sizeof(char)*200);
411     char *temp_string=(char *)malloc(sizeof(char)*1000);
412     
413     srand(time(0));
414     temp=rand()%20+1;
415     itoa(temp,temp_string,10);
416     
417     for(count=1;count<=5;count++){ 
418 
419         op_num=rand()%4;
420         op[0]=basic_op_de[op_num];
421         op[1]='\0';
422         LR=rand()%2;
423         if(LR==0){          //上一步的表达式在左侧
424         
425             left=rand()%20+1;
426             itoa(left,left_string,10);
427             strcat(temp_string,op);
428             strcat(temp_string,left_string);
429         } 
430         else{            //上一步的表达式在右侧
431         
432 
433             left=rand()%20+1;
434             itoa(left,left_string,10);
435             strcat(left_string,op);
436             strcat(left_string,temp_string);
437             strcpy(temp_string,left_string);
438         }
439         LR=rand()%5;
440         if(LR<=1){           //加括号
441         
442             char zuokuohao[200]="(",youkuohao[4]=")";
443             strcat(zuokuohao,temp_string);
444             strcat(zuokuohao,youkuohao);
445             strcpy(temp_string,zuokuohao) ;
446         }  
447        
448     } 
449     
450     cout<<"题目是:"<<temp_string<<endl<<endl;    
451     
452     strcat(temp_string,"#");
453    
454     result=EvaluateExpression_de(temp_string);
455     
456     cout<<"请输入你的答案:(保留两位小数)     ";
457     cin>>stu_answer;
458     cout<<endl<<"正确答案为:    "<<setprecision(2) <<std::fixed<<result<<endl<<endl;
459     if(result==stu_answer)
460         cout<<"恭喜你,答对了"<<endl<<endl;
461     else
462         cout<<"答错了,没关系,这道题有点难"<<endl<<endl;
463     
464     
465     } 
466     if(swi==2){
467         int count ,left ,right ,op_num,LR,temp;
468     
469     char *op=(char *)malloc(sizeof(char)*3); 
470     char *left_string=(char *)malloc(sizeof(char)*200);
471     char *right_string=(char *)malloc(sizeof(char)*200);
472     char *temp_string=(char *)malloc(sizeof(char)*1000);
473     char *temp_string_right=(char *)malloc(sizeof(char)*200);
474     char *result=(char *)malloc(sizeof(char)*1000);
475     
476     char stu_answer[100];
477     
478     srand(time(0));
479     temp=rand()%20+1;
480     itoa(temp,temp_string,10);
481     strcat(temp_string,"/");
482     temp=rand()%50+1;
483     itoa(temp,temp_string_right,10);
484     strcat(temp_string,temp_string_right);
485     
486     for(count=1;count<=5;count++){
487      
488 
489         op_num=rand()%3;
490         op[0]=basic_op[op_num];
491         op[1]='\0';
492         LR=rand()%2;
493         if(LR==0){          //上一步的表达式在左侧
494         
495             right=rand()%50+1;
496             itoa(right,right_string,10);
497             left=rand()%20+1;
498             itoa(left,left_string,10);
499             strcat(temp_string,op);
500             strcat(temp_string,left_string);
501             strcat(temp_string,"/");
502             strcat(temp_string,right_string);
503         } 
504         else{          //上一步的表达式在右侧
505         
506             right=rand()%50+1;
507             itoa(right,right_string,10);
508             left=rand()%20+1;
509             itoa(left,left_string,10);
510             strcat(left_string,"/");
511             strcat(left_string,right_string);
512             strcat(left_string,op);
513             strcat(left_string,temp_string);
514             strcpy(temp_string,left_string);
515         }
516         LR=rand()%5;
517         if(LR<=1){           //加括号
518         
519             char zuokuohao[200]="(",youkuohao[4]=")";
520             strcat(zuokuohao,temp_string);
521             strcat(zuokuohao,youkuohao);
522             strcpy(temp_string,zuokuohao) ;
523         }  
524        
525     } 
526     cout<<"题目是:"<<temp_string<<endl<<endl;    
527     
528     strcat(temp_string,"#");
529    
530     strcpy(result,EvaluateExpression(temp_string));
531     
532     cout<<"请输入你的答案:     ";
533     cin>>stu_answer;
534     cout<<endl<<"正确答案为:    "<<result<<endl<<endl;
535     if(strcmp(result,stu_answer)==0)
536         cout<<"恭喜你,答对了"<<endl<<endl;
537     else
538         cout<<"答错了,没关系,这道题超纲了"<<endl<<endl;
539     }
540 
541 }
显示代码

 

运行截图:

                                                                      结果为小数

 

                        结果为分数

github仓库路径:https://github.com/DJJune/calculator

 

posted on 2016-09-29 18:45 阿俊·铜须 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/JuneBronzebeard/p/5920928.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值