C语言程序设计第六次作业——循环结构(2)
(一)改错题
序列求和:输入一个正实数eps,计算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... ,精确到最后一项的绝对值小于eps(保留6位小数)。
输入输出样例:
Input eps:1E-4
s = 0.835699
源程序(有错误的程序)
#include<stdio.h>
int main()
{
int flag,n;
double eps,item,s;
printf("Input eps: ");
scanf("%f",&eps);
flag = 1;
s = 0;
n = 1;
do{
item = 1/ n;
s = s + flag * item;
flag = -flag;
n = n + 3;
}while( item < eps)
printf( "s = %f\n",s);
return 0;
}
错误一:
错误原因:while语句后面没有分号
改正方法:在while( item < eps)的后面加上一个“;”
改正错误后,编译没有错误
输入数据验证
程序错误
错误二:
错误原因:第八行输入语句有问题,不应该用%f
改正方法:将%f改为%lf
错误三
错误原因:第13行中的运算为整型运算,并不能出现实数
改正方法:将“item = 1/ n”中的“1”改成“1.0”
改正后,输入数据,程序仍然错误
错误四
错误原因:输出语句有问题,%f错误
改正方法:将%f改为%lf
错误五
错误原因:循环语句有错误,while语句括号里面的语句错误
改正方法:将“while( item > eps)”里的“<”改成“>”
将改正后的程序输入数据进行验证
附上改正后的程序:
#include<stdio.h>
int main()
{
int flag,n;
double eps,item,s;
printf("Input eps: ");
scanf("%lf",&eps);
flag = 1;
s = 0;
n = 1;
do{
item = 1.0/ n;
s = s + flag * item;
flag = -flag;
n = n + 3;
}while( item >= eps);
printf( "s = %lf\n",s);
return 0;
}
(二)学习总结
1.语句while(1)和for(;;)是什么意思?,如何保证这种循环能正常执行?
答:两个语句都是循环语句,并且都是无限循环,也就是我们说的死循环,这种循环适用于不清楚循环应该运行的次数的循环。while()的括号内的判断方是括号内的条件是否为真,只要括号内为任意非零数值,均判断为真,所以不一定为1,其他的非零数值均可,如:1,-5等均可。 而for循环,其判断依据是根据for(;;)的括号内的三个表达式来判断真假,第二个表达式为循环的条件,若第二个表达式为空,则循环停下来的条件就会缺失,循环语句则会无限循环。
若要保证这种循环正常执行,就必须保证其判断条件为“1”,也就是真,即语句本身不能出现错误,并且不会出现循环控制语句,即不出现break语句等。
2.一般情况下,设计循环结构时,使用for、while、do while三种语句都可以,并且三种语句可以相互转换,但是,在某些特定情况下,我们应该优先选择某种语句来快速实现循环设计。如果有如下情况:
(1)循环次数已知
(2)循环次数未知,但循环条件在进入循环时明确
(3)循环次数未知,且循环条件在进入循环时未知,需要在循环体中明确
针对上面三种情况,分别采用什么循环语句实现比较好?对每种情况,用我们完成的两次循环结构作业中的题目加以说明。
答:(1)循环语句已知的情况下用for语句比较好,因为for语句中含有明确的将循环停止的语句。如pta循环第一次作业中,求奇数分之一序列前N项和这一题,此题便用for语句比较方便,明确循环的次数,选定一个初值,明确结束条件,便可以得出答案。
(2)循环次数未知,但循环条件在进入循环时明确,这种情况使用while语句比较好,由于循环次数未知,但是已知某些条件,便可以利用循环。如怕他循环第二次作业中,韩信点兵问题就是利用while语句,利用先循环在判断的形式,该问题的循环次数为多少我们在不经过计算的情况下并不知道,但是题目所给出的条件可以让我们写出循环停止的语句,所以利用while语句比较好。
(3)循环次数未知,且循环条件在进入循环时未知,需要在循环体中明确,这样的情况我们一般利用do while语句。如pta循环第二次作业中的掉入陷阱的数字的问题,我们对循环执行的次数以及循环停止的条件并不清楚,do while循环的执行方式为先进入循环体执行一次循环体,之后再判断循环条件是否成立,这样利用循环体我们就可以使循环执行下去,来满足题目要求。
3.有如下问题:输入一批学生成绩,以-1作为结束,计算学生的平均成绩。
要求分别用for语句、while语句、do while语句三种循环语句实现,并说明你认为哪种形式更合适?
(1)若使用for语句,程序如下:
#include<stdio.h>
int main(void)
{
int grade=0,sum=0,i=0;
double average=0.0;
for(;;)
{
scanf("%d",&grade);
if(grade!=-1)
{
sum = sum +grade;
i++;
}
else if(grade==-1)
{
break;
}
}
average = sum / i;
printf("%f",average);
return 0;
}
(2)若使用while语句,程序如下:
#include <stdio.h>
int main()
{
double sum = 0.0, n = 0.0, average = 0.0;
int num = 0;
sum = 0.0;
num = 0;
while (1)
{
scanf("%lf", &n);
if (n == -1)
{
break;
}
sum += n;
num++;
}
average = sum / num;
printf("%f", average);
return 0;
}
(3)若使用do while语句,程序如下:
#include<stdio.h>
int main(void)
{
int grade=0,sum=0,i=0;
double average=0.0;
i=0;
do
{
scanf("%d",&grade);
sum = sum + grade;
i++;
}
while(grade!=-1) ;
average = (sum+1) / (double)(i-1);
printf("%f",average);
return 0;
}
(4)无限循环。程序如下:
#include<stdio.h>
int main(void)
{
int n = 0,sum = 0,count = 0;
for(;;)
{
scanf("%d",&n);
if(n < 0)
{
break;
}
else
{
sum += n;
count++;
}
}
if(count == 0)
{
count++;
}
printf("average = %.1f\n",(double)sum / count);
return 0;
}
从程序代码上来看,while循环以及do while循环比较简洁,但是for循环和无限循环我认为更加易懂,综合来说我认为while语句更加合适,因为输入时学生数量是未知的,所以for循环不太好,而当我们输入完事,循环条件在进入循环时已经明确,所以比do while循环好,相比无限循环的繁琐,while循环比较简洁,所以while循环比较好。
4.运行下面程序,输入1到10,结果分别是什么?为什么?
运行程序(1)结果如下图:
运行程序(2)结果如下图:
原因:两个程序结果输出显然不同,差别就在于一个为break语句跳出循环,另一个为continue。if语句后面的内容是break语句,表示跳出循环,假如为循环嵌套形式的时候,当循环执行完for语句的时候,到达break语句,break语句会直接跳出距离他最近的循环,而不执行下一个循环;但continue语句则不同,当循环执行完for语句的时候,到达continue语句,continue语句会略过continue后面的内容,执行距离他最近的循环的判断。所以这道问题,用break语句显然不能满足要求,应该使用continue语句。
(三)实验总结
1.求给定精度的简单交错序列部分和问题
(1)题目
本题要求编写程序,计算序列部分和 1 - 1/4 + 1/7 - 1/10 + ... 直到最后一项的绝对值不大于给定精度eps。
(2)流程图
(3)源代码
#include<stdio.h>
#include<math.h>
int main()
{
int n = 1;
double eps,a = 1.0,S = 1.0,sum = 0.0;
scanf("%lf",&eps);
do
{
a = 1.0 / (S* pow(-1,n+1));
S = S + 3 ;
sum = sum + a;
n++;
}
while(fabs(a) > eps);
printf("sum = %lf",sum);
return 0;
}
(4)实验分析
问题:输出0.0000000
解决办法:将计算结果强制转化为double型
(5)pta提交列表
2.猜数字游戏
(1)题目
猜数字游戏是令游戏机随机产生一个100以内的正整数,用户输入一个数对其进行猜测,需要你编写程序自动对其与随机产生的被猜数进行比较,并提示大了(“Too big”),还是小了(“Too small”),相等表示猜到了。如果猜到,则结束程序。程序还要求统计猜的次数,如果1次猜出该数,提示“Bingo!”;如果3次以内猜到该数,则提示“Lucky You!”;如果超过3次但是在N(>3)次以内(包括第N次)猜到该数,则提示“Good Guess!”;如果超过N次都没有猜到,则提示“Game Over”,并结束程序。如果在到达N次之前,用户输入了一个负数,也输出“Game Over”,并结束程序。
(2)流程图
(3)源代码
#include<stdio.h>
int main()
{
int M,N,n = 0,math;
scanf("%d%d",&M,&N);
do
{
n++;
scanf("%d",&math);
if(math<0)
{
printf("Game Over");
break;
}
else if(n>N)
{
printf("Game Over");
break;
}
else if(math==M)
{
if(n==1)
{
printf("Bingo!");
break;
}
else if(n==2||n==3)
{
printf("Lucky You!");
break;
}
else
{
printf("Good Guess!");
break;
}
}
else if(math<M)
{
printf("Too small\n");
}
else if(math>M)
{
printf("Too big\n");
}
}
while(1);
return 0;
}
(4)实验分析
问题:输入正确答案后,仍然输出gameover
解决办法:在Bilgo加上exit(0)
(5)pta提交列表
3.求奇数和问题
(1)题目
本题要求计算给定的一系列正整数中奇数的和。
(2)流程图
(3)源代码
#include <stdio.h>
int main()
{
int N,sum=0;
while(1)
{
scanf("%d",&N);
if(N%2!=0&&N>0)
{
sum+=N;
}
if(N<=0)
{
break;
}
}
printf("%d",sum);
return 0;
}
(4)实验分析
问题:输入-1后,-1也假如计算
解决办法:没有及时退出循环,将循环变量减一次,
(5)pta提交列表
(四)博客互评
李晓晓http://www.cnblogs.com/Reloaded/p/7825734.html
刘梦醒http://www.cnblogs.com/hbnydx/p/7858643.html
滕文清http://www.cnblogs.com/tengwenqing/p/7856853.html