• 四则运算三


    这一周,老师提出了新的要求:

    1.学生写的程序必须能判定,用户输入的答案是否正确;

    • 例如程序输出:20-5=?用户输入15,那么程序就会反馈正确,然后继续出题。直到三十道题目结束,程序最后告诉用户做对了几道题。

    2.程序必须能够处理四种运算的混合算式;

    • 20-5*2=?         正确答案是10.
    • 20-5*2+9/3=?  正确答案是13.

    注意:

          连续的减法和除法,应该遵循左结合的规定。

          连续除法要打括号,否则会引起歧义。

    针对这一次的练习,只需只需在上一次的基础上加上表达的式的求值即可,只是就需要用到数据结构中的栈来解决。说是简单,但是实现起来却不容易,数据结构一直是我头疼的东西。和我的同学比起来真的是自愧不如,这次他和我一直,询问了他许久。

    最后在上一次的基础上,增加了一个表达式求解的模块,具体代码如下:

      1 // 按要求随机生成四则运算  王世强 2015/3/15  
      2 #include<iostream>
      3 #include<stdlib.h>
      4 #include<iomanip>
      5 #include<time.h>  
      6 #include<stdio.h> 
      7 #include"math.h"  
      8 #define true 1   
      9 #define false 0   
     10 #define OPSETSIZE 7  
     11 #define random() (rand()%100000)  
     12 #include"string.h"   
     13 typedef int Status;
     14 using namespace std;   
     15   
     16 unsigned char Prior[7][7] =  
     17 { // 运算符优先级表   
     18     // '+' '-' '*' '/' '(' ')' '#'    
     19     /*'+'*/'>','>','<','<','<','>','>',  
     20     /*'-'*/'>','>','<','<','<','>','>',  
     21     /*'*'*/'>','>','>','>','<','>','>', 
     22     /*'/'*/'>','>','>','>','<','>','>',
     23     /*'('*/'<','<','<','<','<','=',' ', 
     24     /*')'*/'>','>','>','>',' ','>','>',
     25     /*'#'*/'<','<','<','<','<',' ','=', 
     26 };   
     27   
     28 typedef struct StackChar  
     29 {  
     30     char c;   
     31     struct StackChar *next;   
     32 }SC;       //StackChar类型的结点SC  
     33   
     34 typedef struct StackFloat  
     35 {  
     36     float f;   
     37     struct StackFloat *next;   
     38 }SF;       //StackFloat类型的结点SF  
     39   
     40 SC *Push(SC *s,char c)          //SC类型的指针Push,返回p  
     41 {  
     42     SC *p=(SC*)malloc(sizeof(SC));   
     43     p->c=c;   
     44     p->next=s;   
     45     return p;   
     46 }   
     47   
     48 SF *Push(SF *s,float f)        //SF类型的指针Push,返回p  
     49 {  
     50     SF *p=(SF*)malloc(sizeof(SF));   
     51     p->f=f;   
     52     p->next=s;   
     53     return p;   
     54 }   
     55  
     56 SC *Pop(SC *s)    //SC类型的指针Pop  
     57 {  
     58     SC *q=s;   
     59     s=s->next;   
     60     free(q);   
     61     return s;   
     62 }   
     63   
     64 SF *Pop(SF *s)      //SF类型的指针Pop  
     65 {  
     66     SF *q=s;   
     67     s=s->next;   
     68     free(q);   
     69     return s;   
     70 }   
     71   
     72 float Operate(float a,unsigned char theta, float b)      //计算函数Operate  
     73 {  
     74     switch(theta)  
     75     {  
     76     case '+': return a+b;   
     77     case '-': return a-b;   
     78     case '*': return a*b;   
     79     case '/': return a/b;   
     80     default : return 0;   
     81     }   
     82 }   
     83   
     84 char OPSET[OPSETSIZE]={'+','-','*','/','(',')','#'};   
     85   
     86 Status In(char Test,char *TestOp)  
     87 {  
     88     int Find=false;   
     89     for (int i=0; i< OPSETSIZE; i++)  
     90     {  
     91         if(Test == TestOp[i])  
     92             Find= true;   
     93     }   
     94     return Find;   
     95 }   
     96   
     97 Status ReturnOpOrd(char op,char *TestOp)  
     98 {   
     99     for(int i=0; i< OPSETSIZE; i++)  
    100     {  
    101         if (op == TestOp[i])  
    102             return i;  
    103     }  
    104 }  
    105   
    106 char precede(char Aop, char Bop)  
    107 {   
    108     return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];   
    109 }   
    110   
    111 float EvaluateExpression(char* MyExpression)  
    112 {   
    113     // 算术表达式求值的算符优先算法  
    114     // 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合   
    115     SC *OPTR=NULL;       // 运算符栈,字符元素   
    116     SF *OPND=NULL;       // 运算数栈,实数元素   
    117     char TempData[20];   
    118     float Data,a,b;   
    119     char theta,*c,Dr[]={'#',''};   
    120     OPTR=Push(OPTR,'#');   
    121     c=strcat(MyExpression,Dr);   
    122     strcpy(TempData,"");//字符串拷贝函数   
    123     while (*c!= '#' || OPTR->c!='#')  
    124     {   
    125         if (!In(*c, OPSET))  
    126         {   
    127             Dr[0]=*c;   
    128             strcat(TempData,Dr);           //字符串连接函数   
    129             c++;   
    130             if (In(*c, OPSET))  
    131             {   
    132                 Data=atof(TempData);       //字符串转换函数(double)   
    133                 OPND=Push(OPND, Data);   
    134                 strcpy(TempData,"");   
    135             }   
    136         }   
    137         else    // 不是运算符则进栈   
    138         {  
    139             switch (precede(OPTR->c, *c))  
    140             {  
    141             case '<': // 栈顶元素优先级低   
    142                 OPTR=Push(OPTR, *c);   
    143                 c++;   
    144                 break;   
    145             case '=': // 脱括号并接收下一字符   
    146                 OPTR=Pop(OPTR);   
    147                 c++;   
    148                 break;   
    149             case '>': // 退栈并将运算结果入栈   
    150                 theta=OPTR->c;OPTR=Pop(OPTR);   
    151                 b=OPND->f;OPND=Pop(OPND);   
    152                 a=OPND->f;OPND=Pop(OPND);   
    153                 OPND=Push(OPND, Operate(a, theta, b));   
    154                 break;   
    155             } //switch  
    156         }   
    157     } //while   
    158     return OPND->f;   
    159 } //EvaluateExpression  
    160 
    161 //符号生成
    162 char create_symbol(int n)
    163 {
    164     int n1,j;    
    165     char symbol[1];
    166     if(n==0)
    167     {
    168         n1=2;
    169     }
    170     else if(n=1)
    171     {
    172         n1=4;
    173     }
    174     j=random()%n1;
    175     if(j==0) symbol[0]='+';
    176     else if(j==1) symbol[0]='-';
    177     else if(j==2) symbol[0]='*';
    178     else symbol[0]='/';
    179     return symbol[0];      
    180  } 
    181  //把数字转换成字符串型
    182  string int_string(int number)
    183  {
    184     char str[200];
    185     itoa(number,str,10);
    186     string str_=str;
    187     return str_; 
    188   } 
    189   //真分数合成一个字符串
    190  string combination1(string str1,string str2,char k) 
    191  {
    192      string equation;
    193      equation='('+str1+k+str2+')';
    194      return equation;
    195  } 
    196  //新生成一个数
    197 string create_num(int proper_fs,int range)
    198 { 
    199     int num,num1,num2,fs;
    200     string str_num,str_num1,str_num2;
    201       num=random()%range+1;
    202     str_num=int_string(num);
    203     if(proper_fs==1)
    204     {
    205         fs=random()%3;
    206         if(fs==1)//判断是否生成真分数  
    207         {    
    208             for(;;)
    209             {
    210                 num1=random()%range+1;
    211                  num2=random()%range+1;
    212                 if(num1<num2) break;
    213             }
    214             str_num1=int_string(num1);
    215             str_num2=int_string(num2);
    216             str_num=combination1(str_num1,str_num2,'/');
    217         }
    218     }
    219     return str_num; 
    220   } 
    221  //运算式转换成一个字符串
    222  string combination(string str1,string str2,char k) 
    223  {
    224      string equation;
    225      equation=str1+k+str2;
    226      return equation;
    227  }
    228 
    229 //得出正确答案 
    230 float get_ans(string str)
    231 {
    232     int len;
    233     float ans;
    234     len=str.length();
    235     char num[len];
    236     for(int j=0;j<len;j++)
    237     {
    238         num[j]=str[j];
    239     }
    240     //用堆栈解决。。。 
    241     ans=EvaluateExpression(num);
    242     return ans;
    243 } 
    244  //主函数 
    245 int main()
    246 {
    247     srand((int)time(NULL));  //设置时间种子 ,使得程序每次运行的结果都不同 
    248     int num1,num2,num3,num4,count,n,change,amount,shuchu,range,j,repeat=0,bracket,proper_fs,right=0,wrong=0;
    249     string str_num1,str_num2,temp;
    250     float Answer,InputAns;
    251     cout<<"有无乘除法?1有,0没有:"<<endl;
    252     cin>>n;
    253     cout<<"是否有括号?1有,0没有:"<<endl;
    254     cin>>bracket; 
    255     cout<<"是否有真分数?1有,0没有:"<<endl;
    256     cin>>proper_fs; 
    257     cout<<"请输入数字范围:"<<endl;
    258     cin>>range; 
    259     cout<<"请输入出题数量:"<<endl;
    260     cin>>amount; 
    261     string Equation[amount];
    262     char symbol;
    263     cout<<amount<<"道四则运算题如下:"<<endl; 
    264     for(int i=0;i<amount;i++)
    265     {    
    266         count=random()%3+2;
    267         str_num1=create_num(proper_fs,range);
    268         str_num2=create_num(proper_fs,range);
    269         symbol=create_symbol(n);
    270         Equation[i]=combination(str_num1,str_num2,symbol);
    271         if(count>2)
    272         {
    273             for(count;count>2;count--)
    274             {
    275                 symbol=create_symbol(n);
    276                 str_num1=Equation[i];
    277                 if(bracket==1)
    278                 {
    279                     change=random()%3;
    280                     if(change==0)
    281                     {
    282                        str_num1='('+str_num1+')';
    283                      }
    284                 } 
    285                 symbol=create_symbol(n);
    286                 str_num2=create_num(proper_fs,range);    
    287                 change=random()%2;
    288                 if(change==0)
    289                 {
    290                     temp=str_num1;
    291                     str_num1=str_num2;
    292                     str_num2=temp;
    293                 }                
    294                 Equation[i]=combination(str_num1,str_num2,symbol);
    295             }
    296         }
    297         //判断是否重复
    298          for(j=0;j<i;j++)
    299          {
    300              if(Equation[j]==Equation[i])
    301              {
    302                 i=i-1;
    303                 repeat=1;
    304                 break;
    305              }
    306          }
    307          if(repeat!=1)//若不重复,则输出 
    308          {     
    309             cout<<Equation[i]<<"=";
    310             //判断结果是否正确
    311             cin>>InputAns;
    312             Answer=get_ans(Equation[i]);
    313             Answer*=100;
    314             int temp=(int)Answer;
    315             Answer=((double)temp)/100.00;
    316             if(InputAns==Answer)
    317             {
    318                 cout<<"回答正确!"; 
    319                 right++;
    320             }
    321             else
    322             {
    323                 cout<<"回答错误!正确答案为";
    324                 cout<<setprecision(2)<<fixed<<Answer;
    325                 wrong++;
    326             } 
    327             cout<<endl;
    328          }
    329     }
    330     cout<<"一共答对"<<right<<"道题,答错"<<wrong<<"道题。"<<endl; 
    331 }
     

     下面是运行结果截图:

    总结:这次的练习,熟悉了数据结构的知识,但是对我来说还是一个空缺部分,希望能够补上。

    这次和我结队的同学是高逸凡,附一张我俩合作时的照片

    项目计划总结:

    日期&&任务 听课 编写程序 阅读相关书籍 网上查找资料   日总计
    周一 2 3 2   7
    周二   2    2 4
    周三          
    周四 2 2     4
    周五   2  1   3
    周六      2   2
    周日          
    周总计 4 9 5 2 20

      时间记录日志:

    日期 开始时间 结束时间 中断时间 净时间 活动 备注
    3/4 14:00 15:50 10 100 听课 软件工程上课
      16:00 18:20   140 编写程序 任务3
      19:00 20:00  10 50 编写程序 任务3
      20:00 21:00   60 网上查找资料,阅读 《构建之法》
    3/15 16:00 18:00  10 110 查资料,编写程序 作业3
      19:00 21:10  10 120 编写程序 任务3
    3/16            
    3/17 14:00 15:50  10 100 听课 软件工程上课
      19:00 21:20  20 100 查资料,编写程序 休息,聊天,作业3
    3/18 8:00 10:05  5 120 修改,编程 任务3
      16:10 17:20  10 60 阅读  《构建之法》
    3/19 19:20 21:50  30 120 修改程序,写博客 休息,谈论问题,修改,发表博客
    3/13 19:00 19:30   30 阅读书籍 计划阅读《梦断代码》

    缺陷记录日志:

    日期 编号 类型 引入阶段 排除阶段 修复时间 修复缺陷
    3/18 1 20 编码 编译 120min  
      描述:栈的定义及使用,总是报错!

    队友博客地址:http://www.cnblogs.com/yifan2016/p/5296389.html

  • 相关阅读:
    [luoguP2770] 航空路线问题(最小费用最大流)
    javascript技巧大全套
    jLim
    自己封装的Ajax
    JavaScript函数调用规则
    JavaScript模板引擎使用
    JavaScript MD5
    JavaScript SHA-1
    JavaScript Map对象的实现
    javascript中的_return_false和return_true
  • 原文地址:https://www.cnblogs.com/wsqJohn/p/5294841.html
Copyright © 2020-2023  润新知