软件工程第一周作业

时间:2021-01-17 21:54:47

程序的实现思路:

1、产生随机的数字和运算符,这是组成题目的零件。

数字分为整数和真分数。需要注意的是,为了保证正确,真分数应该要检查(1)分母不为0,(2)不能约分;同时为了避免计算结果是NaN或∞的情况,出于程序简单考虑,生成的整数都是正数。

运算符是简单的四则运算。

2、调用1中的功能,生成题目并计算结果。

在这里控制参与运算的数的个数是随机的、某个位置生成整数还是分数也是随机的。生成题目只需要简单的循环调用就可以了。

计算题目结果使用转化为运算符前缀式的方法。因为开始写的时候没有考虑加括号,直接用函数返回值压栈计算,再在这个基础上加括号就不方便了。这里也可以看见,一个函数最好只实现一个功能。

3、输入输出部分。

首先在屏幕打印一个简单的界面,然后循环地输出题目、输入结果、判断正误,最后给出统计结果。

 

以下是代码和结果:

#include <stdio.h>
#include
<stdlib.h>
#include
<limits.h>
#include
<time.h>

#define limit 30 //分母的范围
int n; //运算数的范围

int FindCommonFactor(int p,int q)
{
//返回最大公因数,默认2<=p<q;
int i; //cursor
int commonfactor=1; //common factor

for(i=2;i<=p;i++)
{
if(p%i==0 && q%i==0)
{
commonfactor
*=i;
p
/=i;
q
/=i;
i
=2;
}
}
return commonfactor;
}

float ProperFraction(char *s,int *i)
{
//生成真分数存入s中,返回生成的数
int p=0; //分子
int q=0; //分母
int cf; //common fraction

while(q==0 || q==1) //生成分母,分母不能是0或1
q=rand()%limit;
while(p==0) //生成分子,分子<分母且p!=0
p=rand()%q;

if(p>1) //格式化分数
{
cf
=FindCommonFactor(p,q);
p
/=cf;
q
/=cf;
}

s[
*i]='('; //存入字符串
(*i)++;
if(p<10)
{
s[
*i]=p+'0';
(
*i)++;
}
else
{
s[
*i]=p/10+'0';
(
*i)++;
s[
*i]=p-(s[*i-1]-'0')*10+'0';
(
*i)++;
}
s[
*i]='/';
(
*i)++;
if(q<10)
{
s[
*i]=q+'0';
(
*i)++;
}
else
{
s[
*i]=q/10+'0';
(
*i)++;
s[
*i]=q-(s[*i-1]-'0')*10+'0';
(
*i)++;
}
s[
*i]=')';
(
*i)++;

return (float)p/(float)q;
}

int Operator(char *s,int *i)
{
//随机生成运算符,存入字符串,返回运算符编号
int o=rand()%4;
if(o==0) s[*i]='+';
if(o==2) s[*i]='-';
if(o==1) s[*i]='*';
if(o==3) s[*i]='/';
(
*i)++;
return o%2+1;
}

int Decimal(char *s,int* i)
{
//随机生成整数,存入字符串,返回这个整数
int num=0; //生成数
int tmp[10]={0}; //暂存数组
int j=0; //cursor
int substitude=0; //替身

while(num==0)
num
=rand()%n;
substitude
=num;
while(num>0) //反序按位拆开
{
tmp[j]
=num%10;
num
/=10;
j
++;
}
for(j--;j>=0;j--) //存入字符串
{
s[
*i]=tmp[j]+'0';
(
*i)++;
}

return substitude;
}

int Rank(char x,char y){
//x>y return1; x<=y return0;
if(x=='+' || x=='-')
x
=1;
if(x=='*' || x=='/')
x
=2;
if(x=='#')
x
=0;

if(y=='+' || y=='-')
y
=1;
if(y=='*' || y=='/')
y
=2;
if(y=='#')
y
=0;

return (int)x>=(int)y;
}

float Question(char *s)
{
//生成混合运算的字符串,返回计算结果
int i=0; //cursor
int j=0; //cursor
int DorF; //Decimal or Fraction
int len=0; //参与运算数的数量
char stack[11]="#"; //符号栈,栈底压入最低级的符号
float result[10]={0}; //结果栈
int stacktop=1; //符号栈顶
int resulttop=0; //结果栈顶
float newnum=0; //新生成数

while(len<2) //参与运算的数至少有2个
len=rand()%11;

for(j=0;j<len-1;j++)
{
DorF
=rand()%2; //随机生成数
if(DorF)
newnum
=(float)Decimal(s,&i);
else
newnum
=ProperFraction(s,&i);
result[resulttop]
=newnum; //新数入栈
resulttop++;
Operator(s,
&i); //生成运算符

while(Rank(stack[stacktop-1],s[i-1])) //弹出运算符并计算
{
switch((int)stack[stacktop-1]) //计算
{
case '+':result[resulttop-2]+=result[resulttop-1];break;
case '-':result[resulttop-2]-=result[resulttop-1];break;
case '*':result[resulttop-2]*=result[resulttop-1];break;
case '/':result[resulttop-2]/=result[resulttop-1];break;
}
resulttop
--; //修正结果栈
stacktop--; //弹出运算符
}
stack[stacktop]
=s[i-1]; //新运算符入栈
stacktop++;
}
DorF
=rand()%2;
if(DorF)
newnum
=(float)Decimal(s,&i);
else
newnum
=ProperFraction(s,&i);
result[resulttop]
=newnum; //新数入栈
resulttop++;
while(stacktop>1) //剩下的计算
{
switch((int)stack[stacktop-1]) //计算
{
case '+':result[resulttop-2]+=result[resulttop-1];break;
case '-':result[resulttop-2]-=result[resulttop-1];break;
case '*':result[resulttop-2]*=result[resulttop-1];break;
case '/':result[resulttop-2]/=result[resulttop-1];break;
}
resulttop
--; //修正结果栈
stacktop--; //弹出运算符
}
s[i]
=0; //题目结束

return result[0];
}

float Trans(char *input){
int i=0; //cursor
int p=0; //分子
int q=0; //分母
float num=0; //数值
int neg=0; //负数

if(input[0]=='-')
{
neg
=1;
i
++;
}
while(input[i]!=0 && input[i]!='/')
{
p
*=10;
p
+=input[i]-'0';
i
++;
}
if(input[i]==0)
num
=(float)p;
else
{
i
++;
while(input[i]!=0)
{
q
*=10;
q
+=input[i]-'0';
i
++;
}
if(q<=0)
num
=0.0/0.0;
else
{
if(p!=1 && FindCommonFactor(p,q)!=1)
num
=0.0/0.0;
else
num
=(float)p/(float)q;
}
}
return num;
}

int main(void) {
int i=0;//cursor
int questionnum=0; //题目数量
char question[100]={0}; //题目
float result=0.0; //题目结果
char input[50]={0}; //输入结果
int statistic=0; //统计正确量
float inputnum=0; //输入数值

for(;i<80;i++) //界面
printf("*");
printf(
"\n欢迎使用算式生成器!\n");
printf(
"\n请输入要求:\n");
printf(
"参与计算数的范围:");
scanf(
"%d",&n);
printf(
"生成算式的数量:");
scanf(
"%d",&questionnum);
printf(
"\n");

for(i=0;i<questionnum;i++) //生成题目并判断输入是否正确
{
srand (time(NULL));
result
=Question(question);
printf(
"%s = ",question);
scanf(
"%s",input);
inputnum
=Trans(input);
if(abs(inputnum-result)<=0.000005)
{
printf(
"correct!\n\n");
statistic
++;
}
else
printf(
"error!\n\n");
}

printf(
"correct entry: %d\n",statistic); //统计结果
printf("accuracy: %.2f%%\n",((float)statistic*100)/questionnum);
return 0;
}

软件工程第一周作业