首页 > 代码库 > 第一周作业——小学四则运算题

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

作业要求:

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

    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     else462         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     else538         cout<<"答错了,没关系,这道题超纲了"<<endl<<endl;539     }540 541 }
显示代码

 

运行截图:

技术分享

                                                                      结果为小数

 

技术分享

                        结果为分数

 

技术分享

技术分享

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