利用C语言开发一个小学生算术四则运算测试系统.docx
《利用C语言开发一个小学生算术四则运算测试系统.docx》由会员分享,可在线阅读,更多相关《利用C语言开发一个小学生算术四则运算测试系统.docx(23页珍藏版)》请在冰豆网上搜索。
利用C语言开发一个小学生算术四则运算测试系统
武汉理工大学华夏学院
课程设计
课程名称C语言程序设计
题目利用C语言开发一个“小学生算术四则运算测试系统”
专业____电子商务_____
班级______1091_______
学号_____***********_____
姓名______张宇_______
成绩_________________
指导教师杨沙、王绪梅
2010年6月28日至2010年7月2日
课程设计任务书
设计题目:
利用C语言开发一个“小学生算术四则运算测试系统”
设计目的
1.加深对《C语言程序设计》课程所学知识的理解;
2.掌握结构化程序设计的基本方法;
3.学会编制结构清晰、风格良好、数据结构选择恰当的C语言程序;
4.掌握多模块的C语言程序的调试方法。
设计任务(在规定的时间内完成下列任务)
任务描述:
利用C语言开发一个“小学生算术四则运算测试系统”
该系统是让计算机充当一位给小学生布置作业的算术老师,为学生出题、阅卷
该系统应具备以下功能:
1.为小学生出题(分别进行+、-、*、÷等不同运算)
2.学生做题后,进行评阅;
学生每做一题后,评阅时给出“答题正确,很好”或“答题错误,重做”等字样;
3.加、减、乘、除运算功能可以自由选择实现;
4.运算数值可以控制在两位(或三位)数的四则运算范围内。
具体要完成的任务是:
1完成整个规定任务的设计及调试,得出正确结果,并经教师检查及答辩;
2.写出规范的课程设计说明书;
3.课程设计结束后交设计说明书等文档和设计内容。
设计说明书的主要内容是详细写出在设计过程中所用到的主要技术或方法;
4.从6月28日起,学生每天至少要到设计教室半天以上;
5.课程设计报告按国际通用格式书写,具体格式要求请在网络上查阅
时间安排
6月28日上午1-103教室动员全体学生,给学生下任务书;
下午查阅相关资料;
6月29日~7月1日完成选题的设计及报告的书写;
7月2日上午提交课程设计报告并答辩。
指导教师签名:
2010年6月27日
教研室主任(或责任教师)签名:
2010年6月27日
1、问题描述
1.1在最开始设计此程序过程中,我定义的变量flag为字符型,当把原程序段中对应于下面的程序段的程序段改为:
……
scanf("%d",&temp);
while(temp!
=answer)
{
printf("\n答案错误,重做\n");
printf("\n请输入正确的答案:
\n");
scanf("%d",&temp);
}
printf("\n继续请按y,退出测试请按n\n");
scanf("%c",&flag);
while(flag!
=y&&flag!
=n)
{
printf("\n继续请按1,退出测试请按0\n");
scanf("%d",&flag);
}
……
我将会发现当我做完一题且做对了的时候,无论我输入的是y还是n或者是其他的字符,printf("\n继续请按1,退出测试请按0\n")这个提示在屏幕上出现两次,说明了在第一个scanf("%c",&flag)语句中无论什么,flag!
=y&&flag!
=n都是成立的,这说明了在第一个scanf("%c",&flag)中输入的字符并没有赋给flag。
为了修改正确,我询问了指导老师,后来才知道执行语句scanf("%d",&temp)时候,小学生会输入一个数字,然后在按回车键,在执行语句scanf("%c",&flag)时这个是回车键被赋给了变量flag,而不是输入的字符给了变量flag,此时语句flag!
=y&&flag!
=n不成立,就会造成循环语句while(flag!
=y&&flag!
=n)
一定会执行一次,也就造成了上述结果。
后来我将定义的字符型变量flag改成了整形,并且当输入1时继续做题,当输入0时退出系统,当输入的其他的数字时候,就会被提示输入错误,且要求重新输入。
这样修改后就达到了上述目的。
1.2最开始我没有调用函数srand((unsigned)time(NULL))结果发现连续做两道相同算法的题目时,两次的题目完全一样,也就说明了此程序并不能随机的出题,后来使用了函数srand((unsigned)time(NULL))。
srand((unsigned)time(NULL))这个函数调用中使用time(NULL)函数返回值(当前时间)作实参,初始化随机数发生器。
rand()函数调用返回一个随机数,理论上说,rand()返回一个随机数,但是每次调用时,随机数发生器返回的随机数序列都是一样的,所以,用当前时间(time(NULL)返回值)作种子对随机数发生器进行初始化,由于每次当前时间不一样,所以随机数发生器产生的随机数序列不一样,即rand()函数调用的返回值不一样,就达到了得到真随机数而不是伪随机数的目的,也就成功解决了这个问题。
1.3其他的问题描述见附件1中的question_get()函数中注释中的问题分析部分。
2、详细设计
4.1设计一个函数intquestion_get();,此函数的主要功能是为小学生出题(分别进行+,—,*,/等不同运算),并且保证给出的算式中的数字和结果均不超过三位数。
系统自动计算出正确的答案,然后此正确的答案赋给变量answer。
4.2通过调用函数srand((unsigned)time(NULL));初始化随机数发生器,使rand()函数调用的返回值不一样,这样就使连续做同一种算法时,系统两次给出的算式不相同。
4.3程序中有一个while
(1)和其循环体中的if(flag==0)break;语句,学生可以选择退出程序或者继续做题。
4.4在main()函数外定义一个外部变量type,此变量表示小学生选择题目的类型,当选择1时候需要做加法运算,选择2时候做减法运算,选择3做乘法运算,选择4做除法运算,当选择的不是1234中的一个数时,通过使用while语句要求小学生输入正确的题目类型代号。
4.5提示要求小学生输入自己的答案,并将小学生输入的答案赋给变量temp,然后用while(temp!
=answer)语句判断小学生输入的答案是否与正确答案相同,如果不同则通过此while的循环体提示答案错误,要求重新输入正确答案,直到输入的答案正确后提示答案正确;如果小学生一开始输入的答案是正确的则直接提示答案正确。
4.6定义了一个变量flag,当给flag赋值1时可以继续做题,赋值为0时通过break语句退出整个循环while
(1),此时也就退出了测试系统。
4.7设计函数question_get(),首先在main()函数作函数声明,然后开始设计此函数,考虑到当小学生输入数字1需要做加法运算,输入2时候做减法运算,输入时3做乘法运算,输入4时做除法运算,所以通过条件ifelse语句分情况设计算法。
3.实验环境
Microsoftvisualc++
4.程序调试
源程序:
#include
#include
#include//用到了time()函数,所以要包含time.h头文件//srand(time(NULL))中的time(NULL)就是time函数调用
inttype;
main()
{
intquestion_get();//函数声明
intanswer;
inttemp;
intflag;
4.心得体会
5.1在我们设计程序时候,将一个大的问题分成几个模块,运用不同的函数将这些模块分别设计出来,然后运用函数调用,我们就可以将这些功能不同的模块联系在一起。
5.2在设计程序过程中,我原先定义的变量flag为字符型,当输入y时继续做下题,输入n时退出系统,我发现无论按哪个字母,在看结果时候发现有两条继续测试请按1,退出测试请按0:
语句输出,后来经过老师的讲解我明白了,在连续的2个scanf函数中,以字符形式输入第一个scanf函数时候,回车键会以字符形式存储在第二个scanf函数中。
5.3要使计算机自动为学生出题,使用了函数srand((unsigned)time(NULL));这个函数调用中使用time(NULL)函数返回值(当前时间)作实参,初始化随机数发生器。
rand()函数调用返回一个随机数,理论上说,rand()返回一个随机数,但是每次调用时,随机数发生器返回的随机数序列都是一样的,所以,用当前时间(time(NULL)返回值)作种子对随机数发生器进行初始化,由于每次当前时间不一样,所以随机数发生器产生的随机数序列不一样,即rand()函数调用的返回值不一样,就达到了得到真随机数而不是伪随机数的目的。
5.4深知自己技术水平还不高,编这样的程序遇到了很多困难,但我相信经过今后的不断学习,我的变成能力会有很大的提高。
srand((unsigned)time(NULL));/*srand((unsigned)time(NULL));这个函数调用中使用time(NULL)函数返回值(当前时间)作实参,初始化随机数发生器。
*/
/*rand()函数调用返回一个随机数,理论上说,rand()返回一个随机数,但是每次调用时,随机数发生器返回的随机数序列都是一样的,所以,
用当前时间(time(NULL)返回值)作种子对随机数发生器进行初始化,由于每次当前时间不一样,所以随机数发生器产生的随机数序列不一样,
即rand()函数调用的返回值不一样,就达到了得到真随机数而不是伪随机数的目的。
*/
printf("\t\t\t小学生算术四则运算测试系统\n");
while
(1)
{
printf("\n请你选择测试题目的种类,只需输入数字代号:
\n");
printf("\n1.加法2.减法3.乘法4.除法\n");
scanf("%d",&type);
while(type!
=1&&type!
=2&&type!
=3&&type!
=4)/*如果你不是输入的1234中的一个,则需要重新输入*/
{
printf("\n输入代号错误,请重新输入数字代号:
\n");
printf("\n1.加法2.减法3.乘法4.除法\n");
scanf("%d",&type);
}
answer=question_get();/*通过函数调用返回计算机算出的正确答案*/
printf("\n请输入你的答案:
\n");
scanf("%d",&temp);//学生输入自己的答案
while(temp!
=answer)/*判断学生的答案是否与正确的答案相同,若不同则需要输入正确答案,直到答案正确*/
{
printf("\n答案错误,重做\n");
printf("\n请输入正确的答案:
\n");
scanf("%d",&temp);
}
printf("\n答案正确,很好\n");
printf("\n继续测试请按1,退出测试请按0:
\n");
scanf("%d",&flag);
while(flag!
=1&&flag!
=0)
{
printf("\n继续测试请按1,退出测试请按0:
\n");
scanf("%d",&flag);
}
if(flag==0)
break;
}
}
intquestion_get()/*此函数作用为为小学生出题,并返回计算机算出的正确答案*/
{
inta,b,c;
if(type==1)
{
a=rand()%999;//a=rand()%999则a一定小于999
b=999-a;//等效于数学中a+b=999
b=rand()%b;/*b=rand()%b将b=999-a带入,得b=rand()%(999-a),b等于一个随机数对999-a取余,则b一定小于999-a,即b<999-a,也即保证了a+b<999*/
printf("\n%d+%d=?
",a,b);
return(a+b);
}
/*问题分析:
如果将if(type==1)整体改为:
if(type==1)
{
a=rand()%999;
b=rand()%999;
printf("\n%d+%d=?
",a,b);
return(a+b);
}会发现有时候做加法运算时,a+b的和会超过999,原因在于a和b均为小于999的数,但a+b可以超过999,如:
998+998=?
b=999-a;b=rand()%b;这两条语句成功解决了a+b可能大于999的问题*/
elseif(type==2)
{
b=rand()%999;//b小于999
c=999-b;//等效于数学中c+b=999
c=rand()%c;//将c=999-b代入其,得c=rand()%(999-b),从而保证c小于999-b,即c<999-b,也就保证b+c<999
printf("\n%d-%d=?
",b+c,b);//b+c已经保证小于999了
return(c);
}
/*问题分析:
如果此程序段改为:
elseif(type==2)
{
b=rand()%999;
c=rand()%999;
printf("\n%d-%d=?
",c,b);
return(b-c);
}
则在做减法运算的时候可能会出现一个小的数减一个较大的数而造成结果为负数,例如:
400-800=?
原程序段中c=999-b;和c=rand()%c;成功将c定为了比b小的数,从而不会出现负数*/
elseif(type==3)
{
a=rand()%500;/*a小于500由于a有可能等于0,如果a=0,那么后面的语句b=1000/a不能执行*/
while(a==0)//此循环保证a不等于0且a小于500
{
a=rand()%500;
}
b=1000/a;//等效于数学中b*a=1000
b=rand()%b;/*将b=1000/a代入b=rand()%b,得b=rand()%(1000/a),则b一定小于1000/a,即b<1000/a,也就保证了a*b<1000*/
printf("\n%d*%d=?
",a,b);//前面保证了a*b<1000
return(a*b);
}
/*问题分析:
如果此程序段改为:
elseif(type==3)
{
a=rand()%500;
b=rand()%500;
printf("\n%d*%d=?
",a,b);
return(a*b);
}
则在做乘法时候可能会出现乘积大于999的情况例如:
499*499=?
原程序段很好解决了这个问题,还可以将a=rand()%500;和b=rand()%500;语句改为a=rand()%30和b=rand()%33;
不过这样改不会出现乘数和被乘数至少有一个大于33的情况,例如:
45*458=?
*/
else
{
b=rand()%500;//b小于500由于b有可能等于0,如果b=0,那么后面的语句c=1000/b不能执行
while(b==0)//此循环保证b不等于0且b小于500
{
b=rand()%500;
}
c=1000/b;//等效于数学中b*c=1000
while
(1)//保证执行循环体后c不等于0
{
c=rand()%c;//将c=1000/b代入,得c=rand()%(1000/b),则c一定小于1000/b,保证了b*c<1000
if(c!
=0)//保证c不等于0
break;
}
printf("\n%d/%d=?
",b*c,b);//前面已近保证b*c<1000且c已近保证不等于0,若没有保证c不等于0,则会
return(c);
}
/*问题分析:
如果将此程序段改为:
else
{
b=rand()%500;
while
(1)
{
c=rand()%500;
if(c!
=0)
break;
}
printf("\n%d/%d=?
",b*c,b);
return(c);
}
因为b=rand()%500;所以b有可能为0,所以b*c为0,所以在做除法的时候会出现0除以0的情况,
例如0/0=?
这样的计算在数学中没有意义,而计算机返回的答案是0
*/
}
设计过程中现场提问(或答辩)记载:
1.除法运算中是如何保证算法除尽的?
答:
除法程序段为:
else
{
b=rand()%500;
while(b==0)//此循环保证b不等于0且b小于500
{
b=rand()%500;
}
c=1000/b;
while
(1)
{
c=rand()%c;
if(c!
=0)
break;
}
printf("%d/%d=?
",b*c,b);
return(c);
}
rand()返回一个随机正整数,利用随机数对500求余数,所得的余数赋给b,则b是小于500的正整数,通过循环保证b不等于0,将语句c=1000/b;代入语句c=rand()%c;中,则可以认为c=rand()%(1000/b),那么c一定是小于1000/b的正整数,且b*c一定小于999。
通过循又环保证了c不等于0,printf("%d/%d=?
",b*c,b);语句中b*c为一整数,用它除以整数b,则答案为整数c,所以除法运算可以除尽。
2.如果要求系统规定小学生做完多少道题目后(例如20道题后)自动退出系统且需要统计小学生做对以及做错的个数,如何实现?
答:
只需要将main()函数修改为:
main()
{
intquestion_get();
intanswer;
inttemp;
intn=1;
intright;
intwrong;
intflag;
srand((unsigned)time(NULL));
printf("\t\t\t小学生算术四则运算测试系统\n");
right=0;wrong=0;
while(n<=20)
{
printf("\n请你选择测试题目的种类,只需输入数字代号:
\n");
printf("\n1.加法2.减法3.乘法4.除法\n");
scanf("%d",&type);
while(type!
=1&&type!
=2&&type!
=3&&type!
=4)
{
printf("\n输入代号错误,请重新输入数字代号:
\n");
printf("\n1.加法2.减法3.乘法4.除法\n");
scanf("%d",&type);
}
answer=question_get();
printf("\n请输入你的答案:
\n");
scanf("%d",&temp);
if(temp==answer)
{
++right;
printf("\n答案正确,很好\n");
}
else
{
printf("\n答案错误\n");
++wrong;
}
n++;
}
printf("\n该小学生做对题和做错题的个数分别为:
right=%d,wrong=%d\n",right,wrong);
}
假设老师布置了20道题目,我就定义了一个变量n,并且赋值为1,运用循环while(n<=20)语句(只要n小于等于老师布置的题目数,则小学生需要继续做题,否则,答题完毕,退出程序。
题目中变量right代表做题正确的个数,wrong代表做题错误的个数(在该题做错了的时候没有要求学生重做),当小学生答案正确的时候变量right自增1,错误的时候变量wrong自增1。
这样就达到了题目的要求。
3.小学生不需要选择题目种类,由系统随机给出题目,该如何实现?
答:
只需要将main()函数内的循环while
(1)的循环体中的如下程序段:
printf("\n请你选择测试题目的种类,只需输入数字代号:
\n");
printf("\n1.加法2.减法3.乘法4.除法\n");
scanf("%d",&type);
while(type!
=1&&type!
=2&&type!
=3&&type!
=4)//如果你不是输入的1234中的一个,则需要重新输入
{
printf("\n输入代号错误,请重新输入数字代号:
\n");
printf("\n1.加法2.减法3.乘法4.除法\n");
scanf("%d",&type);
}
换成type=rand()%4;就可以了。
指导教师评语:
成绩评定等级:
指导教师(签名):
2010年7月2日