zoukankan      html  css  js  c++  java
  • 开车啦开车啦

    结对结对!

    @(软件工程第三次作业)[二人结对|极限编程|复查]

    任务要求

    • 1.能够自动生成四则运算练习题
    • 2. :可以定制题目数量
    • 3 :用户设置最大数(如十以内、百以内等)
    • 4. :最好能提供图形用户界面(根据自己能力选做,以完成上述功能为主)

    题目介绍

    每天给孩子绞尽脑汁的出四则运算的算术题,还不能重复,30道题中无重复!天呐!越想越崩溃!
    Emmm,崩溃?不存在的!程序员的阿超丝毫没有溃动。
    但一袋烟的功夫却是一切烦恼的开端....
    (http://www.cnblogs.com/firstblogtoliukehong/p/8542259.html)。

    界面界面!

    我们首先来看来看最直观的界面设计!
    我们是由控制台程序挂载EGE图形库,进行绘图。哈哈,终于可以脱离千篇一律的黑黑的DOS栏了。

    设置事件监听,满足设置要求

    算式生成界面,这里是选择了数值范围为100以内,支持分数,支持运算符有“+”,"-" “x ”,生成题目数为12 道

    这里支持用户输入,然后并检查正误

    用文件格式存储生成的算式和正确答案

    代码

    • 首先给出所有文件的Coding地址

    https://coding.net/u/liukehong666/p/Graphics_Achao/git/blob/master-patch-1/code

    • 然后贴出核心功能代码

      • 算术表达式的运算处理.
      
      float handle(float *num11,char *symbol2 ){  
       int ss[5];
       for(int i=0;i<4;i++){        //把字符表里的元素换成数字
          switch(symbol2[i]){
          case '+':ss[i]=0;break;
           case '-':ss[i]=1;break;
            case '*':ss[i]=2;break;
             case '/':ss[i]=3;break;
             case '(':ss[i]=4;break;
             case '(':ss[i]=5;break;
            }
          ss[4]=6;
      
       }
      initstack(symbol);
      initstack(data);
      push(data,num11[0]);   //第一个数字入栈
      for(int i=0;;)
      {
         if(priority(gettop(symbol),ss[i])==1)  //栈外元素优先级比栈内低  出栈运算
        {
          float a,b;
         float c;
           pop(data,a); //出 两个数
           pop(data,b);
           pop(symbol,c);//出 符号
         // push(symbol,ss[i]);
           switch((int)c){
           case 0:push(data,a+b);break;
           case 1:push(data,b-a);break;
            case 2:push(data,a*b);break;
             case 3:push(data,b/a);break;
             }
      
       }
      else if(priority(gettop(symbol),ss[i])==0)   //若符号栈的最后一个元素和数据栈的元素一样   循环结束 返回data栈的栈顶元素
             {    
                 if(gettop(data)=='(')
                 {i++;
                 continue;
                 }
                 
                 return gettop(data);}
        else {
             push(symbol,ss[i]);                //栈外元素优先级比栈内高  运算数入栈。代码中可以看到,我们对符号预处理是将字符数组转成了整型数组
             push(data,num11[i+1]);
             i++;}
       }
      

    }
    ```
    这里依然采用数据结构课上曾讲过的算符优先算法。数据栈的变化依赖于字符栈的变化,字符栈的变化取决于字符的优先级。这个函数调用的prioity()就是根据制定好的表格,返回的两个字符优先级关系。返回值0,优先级相等,脱括号或是#结束运算;返回值为-1,栈外元素优先级比栈内高 运算数入栈;返回值为1,栈外元素优先级比栈内低 出栈运算。

    ————————————————————————————————————————————————————————————————

    • 随机生成算术表达式
    		
    		char * equals()
    		{char str_equals[50]="";
    	     int s;
    	     char datasymbol,kk;
        //symbol_key++;
         char symbol2[6];
         float num1[20],num2[20];
         int i,j,percentchoice,datachoice,data;
        FILE *fp;
    		//判断按读方式打开一个名叫test的文件是否失败
    			    fp=fopen("record.txt","r+");
    
      
    	   int flag=0;   //flag 判断输出的个数i  若式子的值为负数i--
      
    
        for( i=0;i<EQUAL_NUM;i++)
    	   {
           flag=0;
          for( j=0;j<5;j++) {
           if(random(PERCENT)==1)   //判断生成分数  PERCENT 用来控制生成负数的概率 1/PERCENT
           {
            num2[j]=1+(float)random(MAX); //加1 保证生成的随机数不为0  做分子
            num2[j+1]=num2[j]+(float)random(MAX);   //分母  切分数为真分数
            num1[j]=num2[j]/num2[j+1];
           }
         else
            num1[j]=(float)random(MAX);   //生成整数
            symbol2[j]=symbol1[random(symbol_key)];   //随机生成符号
          }
    
        Squense[i]=handle(num1,symbol2);
    
          /*
          插入括号
          _____________________________________________________
          */
        if(BRACKET_FLAG==1)
        {
        int left,right;
        int temp;
    	   char str_more[5]="";
    
        left=random(3);
        temp=3-left;
    
        right=left+2+random(temp);
    
        for(int i=0,k=0;i<6;i++)
        {
            if(i==left)
            {str_more[i]='(';
            i++;
            }
            if(i==right)
            {str_more[i]=')';
            i++;
            }
            str_more[i]=symbol2[k];
            k++;
        }
    
    
        strncpy(symbol2,str_more,6);
        }
        /*
        ___________________________________________________
        */
    
         char str_equals[50]="";
            for(int j=0,k=0;j<5;j++,k++)
        { char temp[10]="";
            //if(handle(num2,symbol_region)>=0)   //若生成的式子值为正数 输出
                {
            if(symbol2[k]=='(')
            {
                strcat(str_equals,"(");
                k++;
            }
    
    
    
            if(num1[j]>0&&num1[j]<1)    //若要输出的数为分数  就输出相应的分数
               {
                    //cout<<"["<<num2[j]<<"/"<<num2[j]<<"] ";
                    sprintf(temp,"%c%.0f%c%.0f%c",'[',num2[j],'/',num2[j+1],']');
                    strcat(str_equals,temp);
               }
            else if(j<6)
                {sprintf(temp,"%.0f",num1[j]);
    
                strcat(str_equals,temp);
                }
    
               if(symbol2[k]==')')
            {
                strcat(str_equals,")");
                k++;
            }
            if((k<6&&BRACKET_FLAG==1)||(BRACKET_FLAG==0&&k<4))
            {sprintf(temp,"%c",symbol2[k]);
            strcat(str_equals,temp);
            }
    
            //cout<< symbol2[j]<<" ";
    
               }
    
        }
    
        setbkmode(TRANSPARENT);
        setcolor(EGERGB(0x00, 0x00, 0x00));
        outtextxy(160,100+i*20,str_equals);
        fprintf(fp, "%3d :%s  =   %8.2f
     ", i,str_equals,Squense[i]);
        char temp2[8];
        sprintf(temp2,"%.2f",Squense[i]);
    
    	   }
    	   return str_equals;
    	}
    

    这里使用随机数在用户选择的参数中随机生成算术表达式,控制分数为真分数即纯小数,以分数形式代替运算。
    这里有一个十分纠结的问题,可以看到代码中我用注释分隔的一段代码。这里我原本想写成函数调用的,但经过了几番努力始终不合要求。这里功能是根据用户输入决定是生成括号。应该对已有的字符串实现插入操作。用函数的话,应该形参设为 字符数组char[]类型,返回的理应也是首地址,但给出错误信息char 能向char[]类型转化,使用char传入参数的话,却提示出错误信息char * 能向char[]类型转化。只要思想不滑坡,办法总比问题多,我又尝试使用string类型传入,然后返回string类型值让另一string类接受,有提示出 ** cannot convert 'std::string {aka std::basic_string}' to 'char' in return| ** ,然后采用不返回值方式,对传入参数首地址操作,即取insert(string &str)格式传入参数,然后还是提示错误。。。。
    。。。。。。
    所以就不考虑函数调用了,争端代码复制过来了。

    • 主要代码就是这些了,更多的代码还是详见Coding工程文件

    小伙伴介绍

    • 辛娟娟同学呀,可好啦.结对极限复查,在领航员的引领下少走了很多弯路,尽可能的排除了由于低级错误而浪费的大量的调试测试时间。对于驾驶员的急躁耐不住性子,领航员做到了极大的包容,是整个结对氛围快节奏而不紧张。

    • 呐呐呐,开车啦!
      -

    总结

    • 小程序中用到以前写的算术表达式代码功能模块,想直接调用来这边,发现很难接入。觉得代码的封装和规范性都很重要。就例如说,之前写算术表达式求值为边输入边运算,而这里面的输入语句过于分散,无法较快的转为对字符串的处理,如果当时将数据处理写的集中一点,格式转换也就容易了许多了。
    • 在可视化处理上,控件的大小处理通过几次痛苦的更改过程中也有了教训:控件尽量小而独立。这样在后期的界面调整中才能够不去更改所有的布局文件,从而实现微调。虽然前期的剥离,独立分装工作繁琐,但这些相较于后期心理上的和生理上的压力,还是值得的。
    • 代码命名规则上,由于沿用了以前的代码,而以前简单的代码从未考虑在编程的问题,命名规则基本从a,b,c,d顺序而来的,到这次代码量的倍增,明显的变量名出现了重复,可辨识度地,作用范围模糊等问题。由于又是两人编程,两人的命名风格又是不同的,而在前期必要的协商仍然还是很重要的,如,辛同学的symbol1和symbol变量名在我看来就很难分别两个变量的左右。
    • 接下来就是两人结对编程的总结了。在这以前,编程我还是倾向于个人独立完成的。一份代码就应该有一份思想,一种风格。而第二个人的就加入,会是代码结构混乱不已,无法理清头绪。但这次编程任务,改变了我很多以前的想法。虽然代码只有一份思想算法,写的行云流水。但始终还是会跳不出自己固有的套路和经验,无法获得新的想法和理解。就像驾驶员一样,一个人掌控着方向,走着自己认为的捷径,这样永远在自己的世界里看着相同的风景。这个时候,如果服从一个领航员的引导,放弃自己的执着尝试着走不同的路径,即使稍微曲折了一点,但我们可能收获道不一样全新的东西。原来从荆棘小径中笔直前进,如今,选择从大路绕行,你可以领略鲜花和海浪,会发现,噢,这样空间占用会更少一点,抑或是运行速度更快一点。
  • 相关阅读:
    AX ERROR: Could not find my mock parent, most likely I am stale 不及格的程序员
    利用Segue在视图控制器间传值的问题 不及格的程序员
    Creating a Singleton Instance 不及格的程序员
    iPad 通知 UIKeyboardWillShowNotification 不会在keyBoard处在Undock状态下接到通知 不及格的程序员
    Why RootViewController's view is rotated Automatically by System when the app first loaded? 不及格的程序员
    如何弹出UIDatePicker最好 不及格的程序员
    jQuery开始做恶了 不及格的程序员
    what is the SEL,id and IMP,Class ,Method? 不及格的程序员
    Objectivec 字符串比较的陷井 不及格的程序员
    Unable to create any keyboard shortcuts after the iOS 6.1.3 update on iPad. 不及格的程序员
  • 原文地址:https://www.cnblogs.com/firstblogtoliukehong/p/8850011.html
Copyright © 2011-2022 走看看