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


    作业要求:

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

        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]='';
     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]='';
    101                 num=atof(str);
    102                 S1->push(num); 
    103                 i=0;                 //字符串初始化 
    104                 str[i]='';
    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]='';
    246     j=i;
    247     for(i=0;;i++){
    248         Num1_right[i]=Num1[i+j+1];
    249         if(Num1_right[i]=='')   
    250           break;
    251     } 
    252     for(i=0;Num2[i]!='/';i++){
    253         Num2_left[i]=Num2[i];
    254     } 
    255     Num2_left[i]='';
    256     j=i;
    257     for(i=0;;i++){
    258         Num2_right[i]=Num2[i+j+1];
    259         if(Num2_right[i]=='')   
    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]='';                              //初始化 
    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]='';                              //初始化 
    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]='';
    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<<"-----------欢迎使用小学生计算器---------
    "<<endl;
    397     cout<<"--------------输入1;小数计算---------
    "<<endl;
    398     cout<<"--------------输入2;分数计算---------
    "<<endl;
    399     cout<<"--------------输入0;退出---------
    "<<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]='';
    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]='';
    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

    结果为小数

    结果为小数

  • 相关阅读:
    [noip2013]华容道
    [tyvj 1061] Mobile Service (线性dp 滚动数组)
    [bzoj 2726] 任务安排 (斜率优化 线性dp)
    [洛谷 P2365] 任务安排 (线性dp)
    [poj 3666] Making the Grade (离散化 线性dp)
    【模板】manacher算法
    [tyvj 1071] LCIS
    [NOIP 2012] 国王游戏
    [NOIP 2010] 关押罪犯 (二分+二分图判定 || 并查集)
    [NOI 2002] 银河英雄传说 (带权并查集)
  • 原文地址:https://www.cnblogs.com/JuneBronzebeard/p/5920928.html
Copyright © 2020-2023  润新知