结对项目总结

经过多个礼拜的编程,最终终于完成了结对项目。

本次结对项目是基于上次的个人项目完成的。本质上来说,是将上回的计算功能模块化,再加入随机生成算式的功能模块,最后把他们附在界面上调用。

完成项目

1、随机生成算式

2、能选择生成算式的长度

3、能够选择生成算式中数字的位数和精度

4、能够选择生成的括号数量(因为考虑到随机生成,所以控制的数量是括号的最大量而不是固定量)

完整代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<stack>

using namespace std;
#define N 1000
int timer=0;
int ri,wr=0;
int chance=3;
char infix[N];  //中缀表达式(未分离,都在一个字符串里)
char infix2[N];
char expression[N][10];    //保存预处理过的表达式,也就是每个元素都分离过的表达式
char suffix[N][10];        //保存后缀表达式的操作数
int count;//表达式中元素的个数(一个完整到数字(可能不止一位数)或者符号)
int suffixLength;//后缀表达式的长度

struct fra{
    char str[10];//为了在栈中记录符号,所以包括数字全部用char记录
    double up;//分子
    double down;//分母
};
int len = 0;
FILE *fp = fopen("1.txt", "r");
long answer;
fra answer1,answer2;


class cal{
private:
    
    int level(char a){
        switch(a){
        case '#':return 0;
        case '+':
        case '-':return 1;
        case '*':
        case '/':return 2;
        case '^':return 3;
        default:break;
        }
        return -1;
    }
    
    int isDigital(char x){
        if( (x>='0'&&x<='9') )
            return 1;
        return 0;
    }
    
    int isNumber(char *str){
        int i;
        for(i=0;str[i];i++){
            if(isDigital(str[i])==0)return 0;
        }
        return 1;
    }
    /*************************************
    预处理中缀表达式,把连续的字符分离成不同的元素,用字符串数组(expression[][])
    保存,方便后面的计算,因为这里考虑了运算数可能不全是个位数
    比如:(12+3)
    在处理成后缀表达式时,是123+,容易产生歧义(1+23 ? 12+3)
    *************************************/
    void pretreatment(char *str){
        int i,j,numberFlag;
        char temp[3];
        char number[10];
        count=0;
        numberFlag=0;
        for(j=0,i=0;str[i];i++){
            if(isDigital(str[i])==0){
                if(numberFlag==1){
                    number[j]=0;
                    strcpy(expression[count++],number);
                    j=0;
                    numberFlag=0;
                }
                if(str[i]!=' '){
                    temp[0]=str[i];temp[1]=0;
                    strcpy(expression[count++],temp);
                }
            }
            else {
                numberFlag=1;
                number[j++]=str[i];
            }
        }
        
        //    puts("分离后的表达式为");
        //   for(i=0;i<count;i++){
        //       printf("%s ",expression[i]);
        //   }puts("");
        //    puts("");
    }
    /*****************************************
    中缀表达式 转 后缀表达式
    
      遍历字符串,对于str[i]
      str[i]是运算数(或者是字母代替的运算变量)输出;
      str[i]是符号,有两种情况
      (1),是右括号,栈顶元素输出,直到与str[i]匹配的左括号出栈(左括号不用输出打印)
      (2),是运算符,判断str[i]与栈顶元素的优先级,str[i]优先级 不高于 栈顶符号,则栈
      顶元素输出,直到栈空 或者 栈顶符号优先级低于str[i]
    *****************************************/
    void infix_to_suffix(char str[N][10]){
        
        memset(suffix,0,sizeof(suffix));
        suffixLength=0;
        
        stack <char*> st;
        int i=0;
        char Mark[2]="#";
        st.push(Mark);
        do{
            if(isNumber(str[i])==1)//运算数直接保存到后缀表达式中
                strcpy(suffix[suffixLength++],str[i]);
            else if(str[i][0]=='(')        //是 左括号,直接入栈
                st.push(str[i]);
            else if(str[i][0]==')'){        //是 右括号,栈顶出栈,直到与其匹配的左括号出栈
                while( strcmp(st.top(),"(")!=0 ){
                    char temp[10];
                    strcpy(temp,st.top());
                    strcpy(suffix[suffixLength++],temp);
                    st.pop();
                }
                st.pop();
            }
            else if( strcmp(st.top(),"(")==0 )//是 运算符,且栈顶是左括号,则该运算符直接入栈
                st.push(str[i]);
            else {                    //是 运算符,且栈顶元素优先级不小于运算符,则栈顶元素一直
                //出栈,直到 栈空 或者 遇到一个优先级低于该运算符的元素
                while( !st.empty() ){
                    char temp[10];
                    strcpy(temp,st.top());
                    if( level(str[i][0]) > level(temp[0]) )
                        break;
                    strcpy(suffix[suffixLength++],temp);
                    st.pop();
                }
                st.push(str[i]);
            }
            i++;
        }while(str[i][0]!=0);
        
        while( strcmp(st.top(),"#")!=0 ){        //将栈取空结束
            char temp[10];
            strcpy(temp,st.top());
            strcpy(suffix[suffixLength++],temp);
            st.pop();
        }
        
        //   puts("后缀表达式为:");
        //  for(i=0;i<suffixLength;i++){
        //      printf("%s",suffix[i]);
        //  }puts("");
        //  puts("");
    }
    //////////////////////////////////////////////////
    int gcd(int a,int b) {          //最大公约数
        if(b == 0)
            return a;
        else
            return gcd(b,a % b);
    }
    
    void simplify(fra aaa){
        
        int a=gcd(aaa.down,aaa.up);
        aaa.up=aaa.up/a;
        aaa.down=aaa.down/a;
        //    printf("%.1lf/%.1lf\n",aaa.up,aaa.down);
        //    puts("计算出后缀表达式的结果:");
        /*        if(aaa.down==1)
        {
        printf("%lf\n",aaa.up);
        }    
        else
        {
        printf("%lf/%lf\n",aaa.up,aaa.down);
        }
        */
        if(timer==0)
        {
            answer1.up=aaa.up;
            answer1.down=aaa.down;
            timer++;
        }
        else
        {
            answer2.up=aaa.up;
            answer2.down=aaa.down;
            timer--;
        }
        //       printf("%d\n%lf  %lf\n%lf  %lf\n",timer,answer1.up,answer1.down,answer2.up,answer2.down);
    }
    
    /**************************************
    计算后缀表达式的值
    **************************************/
    fra kt[N];
    int stackTop;
    void getResult(char str[N][10]){
        //    fra fras[N];
        stackTop=0;
        /*这里要注意,内存的分配方案导致 i 的位置就在temp[9]旁边,然后strcpy()函数直接拷贝内存的话,在temp越界情况下会覆盖 i 的值*/
        int i;
        //   double temp;
        for(i=0;i<suffixLength;i++){
            if(isNumber(str[i])==1){
                // strcpy(kt[stackTop++].str,str[i]);
                kt[stackTop].up=atof(str[i]);
                kt[stackTop].down=1;
                stackTop++;
            }
            else {
                //            char a[10],b[10];
                fra na,nb,nc;
                
                //  strcpy(a,kt[stackTop-1].str);
                na.up = kt[stackTop-1].up;
                na.down=kt[stackTop-1].down;
                //fras[stackTop-1].up=na;
                //fras[stackTop-1].down=1;
                stackTop--;
                
                //    strcpy(b,kt[stackTop-1].str);
                nb.up = kt[stackTop-1].up;
                nb.down=kt[stackTop-1].down;
                //fras[stackTop-1].up=nb;
                //fras[stackTop-1].down=1;
                stackTop--;
                
                if(str[i][0]=='+')
                {
                    nc.down=nb.down*na.down;
                    nc.up=nb.up*na.down+na.up*nb.down;
                }
                else if(str[i][0]=='-')
                {
                    nc.down=nb.down*na.down;
                    nc.up=nb.up*na.down-na.up*nb.down;
                }
                else if(str[i][0]=='*')
                {
                    nc.up=nb.up*na.up;
                    nc.down=nb.down*na.down;
                    
                }
                else if(str[i][0]=='/')
                {
                    nc.down=nb.down*na.up;
                    nc.up=nb.up*na.down;
                }
                // sprintf(temp,"%lf",nc);
                //strcpy(kt[stackTop++].str,temp);
                kt[stackTop].down=nc.down;
                kt[stackTop].up=nc.up;
                stackTop++;
            }
        }
        sprintf(kt[stackTop-1].str,"%lf",kt[stackTop-1].up/kt[stackTop-1].down);
        //strcpy(kt[stackTop++],temp);
        
        /*    char as[N];
        gets(as);
        if(as==kt[stackTop-1].str)
        puts(" right");
        else{
        puts("wrong");
        }
        */
        simplify(kt[stackTop-1]);
        
        for(i=0;i<suffixLength;i++){
            memset(infix,0,sizeof(infix)); 
            memset(suffix,0,sizeof(suffix));
            memset(expression,0,sizeof(expression));
        }
        
        
    }
    //    char szTest[1000] = {0};
    
    
    void checkanswer()
    {
        //    getchars();
        //       printf("%d/%d\n%d/%d",answer1.up,answer1.down,answer2.up,answer2.down);
        if(answer1.up==answer2.up&&answer1.down==answer2.down)
        {
            printf("right\n");    
            ri++;
        }
        else{
            printf("wrong");
            if(answer1.down!=1)
            {
                printf("\nthe answer is %lf/%lf\n",answer1.up,answer1.down);
            }
            else{
                printf("\nthe answer is %lf\n",answer1.up);
            }wr++;
        }
    }
    
public:
    void getanswer(char str[N]){
    //    gets
                char temp[N];
        strcpy(temp,str);
        pretreatment( strcat(temp," ") );
        infix_to_suffix(expression);
        getResult(suffix);
            checkanswer();
                printf("正确回答%d题\n错误回答%d题\n",ri,wr);
    }
    void work(char str[N])
    {
        char temp[N];
        
        // while(gets(infix)){
        //   getchars();
        
        
        // while(z<3){
        //  if(!feof(fp))
        //    {
        //        memset(infix, 0, sizeof(infix));
        //        fgets(infix, sizeof(infix) - 1, fp); // 包含了\n
        //        printf("%s", infix);        
        
        //    }
        //    getchars();
        //    printf("%s",str);
        strcpy(temp,str);
        pretreatment( strcat(temp," ") );
        infix_to_suffix(expression);
        getResult(suffix);
        //    getchars();
    
        
    
        
    }
};
class tuxinghua{
private:
int kh;//括号总数
int stime;//左括号剩余可生成次数
int lef;
    void fcheck(char str[N],int x){//符号检查
        char fuhao[2];
        //        srand((unsigned)time(NULL));  
        
        
        
        if(x>=0&&x<=21)
        {strcpy(fuhao,"+");}
        else if(x>=22&&x<=43)
        {strcpy(fuhao,"-");}
        else if (x>=44&&x<=65)
        {strcpy(fuhao,"*");}
        else if (x>=66&&x<=87)
        {strcpy(fuhao,"/");}
    //    else
    //    {printf("括号");}
        strncat(str,fuhao,1);
    }
    
    void ncheck(char str[N],int x){//数字检查
        char shuzi[2];
        int as;
        //    Sleep(10);
        //    srand((unsigned)time(NULL));  
        for(int i=0;i<x;i++)
        {
            //    int n=rand()%10;
            as=rand()%10;    
            //    printf("\n%d\n",rand()%100);
            sprintf(shuzi, "%d", as);
            strncat(str,shuzi,1);
        }
    }


void  left(char str[N])
    {
    //    int i=x;
        char zuo[2];
        int b=rand()%3;
        if(b==1&&stime<=kh&&stime>=1){
        strcpy(zuo,"(");
        strncat(str,zuo,1);
//    strncat(str,"(",2);
    //kh--;
    lef++;
    stime--;
        }
    
    
    }
void right(char str[N]){
    int b=rand()%5;    
    char zuo[2];
    if(b==1&&lef>=1){
    strcpy(zuo,")");
        strncat(str,zuo,1);
//    kh--;
    lef--;
        }
}

public:
    int tgetchars(char str[N]){
        if(    gets(str))
            return 1;
        else
            return 0;
    }
    
    
    int shengcheng(char str[N]){
        int clen;
        int max;
        int a=0;
        int f;
lef=0;
        printf("输入长度(奇数)");
        scanf("%d",&clen);
        printf("数字取值范围(位数)");
        scanf("%d",&max);
        printf("最多括号个数");
        scanf("%d",&kh);
        stime=kh;
        srand((unsigned)time(NULL));  
        while(1)
        {
            while(a<clen)
        {
        f=rand()%88;
            
            if(a%2==0)
            {
                left(str);
                ncheck(str,max);
            }
            else
            {    
                right(str);
                fcheck(str,f);
            }
            a++;
            
        }
    
        if(lef==0)
            break;
        else {
    //        printf("aa");
        lef=0;
        memset(infix,0,sizeof(infix)); 
        a=0;
        stime=kh;
        continue;
    
        }
        
        }
        return 1;
    }
};
void main(){
    cal ca;
    tuxinghua x;
    //char infix[N];
    //    getc a;
    int z=0;
    
    
    
    while(1){
        x.shengcheng(infix);
        printf("%s=\n",infix);
        ca.work(infix);
    //    x.tgetchars(infix);
//    gets(infix);
        scanf("%s",&infix);
        //    printf("%s=\n",infix);
    //    ca.work(infix);
        ca.getanswer(infix);
    //        z++;
    }
    
    
}
View Code

本次实验我感悟最深的是项目设计前的规范性。

因为第一次个人项目时没有一个详细的规划,所以在将其模块化时遇到了很大的困难。因此不得不对于整体结构进行了一定的调整。

即便如此,在与生成控制函数耦合的时候,也不得不将一些接口变成了全局变量,来减少代码的改变量。这极大的降低了代码模块化之后的通用性。

同时,因为在完成mfc界面前没有一个详细的规划,所以也遇到了很大的困难。

除此之外,也感到了沟通的重要性,因为在代码编写的过程中,没能提前统一代码的规范和结构,结果在开始编写后遇到了很多问题,让进度不快反慢,有一种“单干反而更轻松”的想法。

原文地址:https://www.cnblogs.com/13070036dj/p/5398380.html