20180925-6 四则运算试题生成

此作业的要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2148

代码的git地址:https://git.coding.net/wangyupan/second-program.git

我们利用随机数来产生字符串:

char GetStr()
{
    int tmp;
    //char str[20];
    int i;
    bool F=true;
    for( i=0; i<7; i++)
    {
        if(i%2==0)
        {
            if(F)
            {
                str1[i]=rand()%10+'0';
            }
            else
            {
                while(1)
                {
                    tmp=rand()%10;
                    if(tmp)
                    {
                        str1[i]=tmp+'0';
                        break;
                    }
                }
            }

        }
        else
        {
            str1[i]=Flag();
            if(str1[i]=='/')
                F=false;
            else
                F=true;
        }
    }
    str1[i]='\0';
    //return str;
}

随机的字符串中添加括号:

        int KH=rand()%5;
        switch(KH)
        {
        case 0:
            for(i=7; i>0; i--)
                str1[i]=str1[i-1];
            for(i=8; i>4; i--)
                str1[i]=str1[i-1];
            str1[0]='(';
            str1[4]=')';
            str1[9]='\0';
            break;
        case 1:
            for(i=7; i>0; i--)
                str1[i]=str1[i-1];
            for(i=8; i>6; i--)
                str1[i]=str1[i-1];
            str1[0]='(';
            str1[6]=')';
            str1[9]='\0';
            break;
        case 2:
            for(i=7; i>2; i--)
                str1[i]=str1[i-1];
            for(i=8; i>6; i--)
                str1[i]=str1[i-1];
            str1[2]='(';
            str1[6]=')';
            str1[9]='\0';
            break;
        case 3:
            for(i=7; i>2; i--)
                str1[i]=str1[i-1];
            str1[2]='(';
            str1[8]=')';
            str1[9]='\0';
            break;
        case 4:
            for(i=7; i>4; i--)
                str1[i]=str1[i-1];
            str1[4]='(';
            str1[8]=')';
            str1[9]='\0';
            break;
        default:
            break;
        }

利用后缀表达式来进行四则运算的实现:

float Pop2(Stack2 *S)
{
    float num;
    if(S->top==NULL)
    {
        return 0;
    }
    Node2 *node=S->top;
    num=node->data;
    S->top=node->next;
    S->cnt--;
    free(node);
    return num;
}
float Arithmetic(char *str)
{
    Stack1 opt;
    Stack2 opd;
    Init2(&opd);
    Init1(&opt);
    int tmp=0,i=0,j;
    //char str[50];
    //scanf("%s",str);
    while(str[i]!='\0'||!Empty1(&opt))
    {
        if(str[i]>='0'&&str[i]<='9')
        {
            tmp=tmp*10+str[i]-'0';
            i++;
            if(str[i]<'0'||str[i]>'9')
            {
                Push2(&opd,tmp);
                tmp=0;
            }
        }
        else
        {
            if(Empty1(&opt)||(GetTop1(&opt)=='('&&str[i]!=')')||Prt(str[i])>Prt(GetTop1(&opt)))
            {
                Push1(&opt,str[i]);
                i++;
                continue;
            }
            if(GetTop1(&opt)=='('&&str[i]==')')
            {
                Pop1(&opt);
                i++;
                continue;
            }
            if((str[i]=='\0'&&!Empty1(&opt))||(str[i]==')'&&GetTop1(&opt)!='(')||Prt(str[i])<=Prt(GetTop1(&opt)))
            {
                switch(Pop1(&opt))
                {
                case '+':
                    Push2(&opd,Pop2(&opd)+Pop2(&opd));
                    break;
                case '-':
                    j=Pop2(&opd);
                    Push2(&opd,Pop2(&opd)-j);
                    break;
                case '*':
                    Push2(&opd,Pop2(&opd)*Pop2(&opd));
                    break;
                case '/':
                    j=Pop2(&opd);
                    Push2(&opd,Pop2(&opd)/j);
                }
                continue;
            }
        }

    }
    return Pop2(&opd);
}

以上是实现功能一和功能二时的关键点,我们学习了四则运算相关的知识,看了一些如何生成随机的博客,实现了上面的代码。

实现功能三,主要就输打印输出到文本中,重复的试题不再出现,下面是关键代码:

        FILE *fp;
        fp=fopen("f.txt","w+");
        float Tans=Arithmetic(str1);
        //printf("2");
        for(i=0; i<j; i++)
        {
            if(Tans==QE[i])
            {
                flag=true;
                break;
            }
        }
        if(flag)
        {
            n++;
            continue;
        }
        QE[j++]=Tans;

        int len=strlen(str1);
        for(i=0; i<len; i++)
        {
            fprintf(fp,"%c",str1[i]);
        }
        fprintf(fp,"=");
        if(len==7)
            fprintf(fp,"  ");
        fprintf(fp,"%12.3f\n",Tans);

实现功能四时,感觉自己的思路一下子就断了,看了几篇博客之后,有了一个比较简单的思路,以下是实现的关键:

求最小公倍数,最大公因数:

int Cm(int a,int b,int c)
{
    int m=a*b;
    while(b)
    {

        int tmp=a;
        a=b;
        b=tmp%b;
    }
    if(c==1)
    {
        return m/a;
    }
    return a;


}

分数的四则运算:

if(Flag()=='+')
        {
            ans+=f;
            f1='+';
        }
        else
        {
            ans-=f;
            f1='-';
        }
        if(Flag()=='-')
        {
            ans-=g;
            f2='-';
        }
        else
        {
            ans+=g;
            f2='+';
        }
        int num1;
        //printf("1");
        int gcd=Cm(b,h,1);
        if(Flag()=='+')
        {
            num1=a*gcd/b+c*gcd/h;
            f3='+';
        }
        else
        {
            num1=a*gcd/b-c*gcd/h;
            f3='-';
        }
        ans+=num1/gcd;

        int num2=num1%gcd;
        int num3=Cm(num2,gcd,2);
        num3=abs(num3);
        num2/=num3;
        gcd/=num3;
        if(tmp)
        {
            printf("%d/%d%c%d/%d%c%d%c%d=",a,b,f3,c,h,f1,f,f2,g);
        }
        else
        {
            printf("%d/%d%c%d/%d*%d%c%d%c%d=  ",a,b,f3,c,d,e,f1,f,f2,g);
        }
        printf("               ");
        if(ans)
        {
            printf("%d ",ans);
        }
        if(num2)
        {
            printf("%d/%d",num2,gcd);
        }
        printf("\n");

感受:

与自己编写的时候还是不一样的吧,多一个脑子干这件事,思路要丰富一些。下面就是我们在写作业的时候遇到的比较重要的点:

1.我们在实现功能一是在想要不要用后缀表达式,朱珅莹觉得可以先不用,先写一个简单的实现加减乘除就可以,可以把功能一给实现了。我觉得要用后缀表达式,不然优先级的处理很麻烦,而且后边有括号的更处理不了。我们最终决定一开始就用后缀表达式来实现四则运算。

2.是否用随机数来生成试题,我们俩一开始都觉得可以手动书写试题,还可以避免随机数的不确定性。写了一段时间以后我觉得这样工作量太大,而且题库太有限,然后我们就利用了随机数。

3.编写程序时,我们遇到了这样一个情况,有个双层循环,满足内层循环里的条件就要跳出外层循环,我一筹莫展。然后朱珅莹就想到了利用一个变量,然后完美的解决了这个问题。果然多一个脑子是可以增加效率的。

4.编写功能四时,我们遇到了好多bug。处理复杂逻辑时,我们俩个人都处于懵逼状态。我们一点点的改,先改掉输出错的情况,然后负号在分母上的情况,一点点的改,bug越来越少,我们思路也渐渐清晰了。城墙一块一块砖垒起来的,bug是一个一个改掉的。

5.生成随机数时,我们忽略了除数不能为零,产生了诡异的bug,我们调了半天终于找了出来。真是粗心害死人呐。

结对编程时的照片

 

posted @ 2018-10-07 16:37  王玉潘  阅读(172)  评论(0编辑  收藏  举报