C语言程序设计第六次作业——循环结构(2)
C语言程序设计第六次作业——循环结构(2)
之前的博客园图片没处理好,对大家说一声抱歉。希望大家能够多多指出我的错误,我来认真修改 ^ - ^ !。
(1)改错题
序列求和:输入一个正实数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;
}
错误信息 1:
错误原因 :while后面的括号没有加“;”。
改正方法:在while后面加上分号“;”。
编译正确,继续执行
错误信息 2:
错误原因:答案不正确,输入和输出用了%f
改正方法:在输入和输出的时候把“%f”改成“%lf”和“%.6lf”。
结果发现答案还是不正确:
错误原因:回头发现do while里面的语句运行不下去了就换一种格式来写
改正方法:把第一个程序改成第二个,如下:
do{
item = 1/ n;
s = s + flag * item;
flag = -flag;
n = n + 3;
}while( item < eps);
do
{
item=flag*1.0/(3*n-2);
s+=item;
flag=-flag;
n++;
}
while(fabs(item)>eps);
**因为在源代码中出现了数学函数fabs(),所以要用include<math.h>。
运行结果:运行正确!
附上正确的源代码:
#include<stdio.h>
#include <math.h>
int main()
{
int flag,n;
double eps,item,s;
printf("Input eps: ");
scanf("%lf",&eps);
flag = 1;
s = 0;
n = 1;
do
{
item=flag*1.0/(3*n-2);
s+=item;
flag=-flag;
n++;
}
while(fabs(item)>eps);
printf( "s = %.6lf\n",s);
return 0;
}
(二)学习总结
1.语句while(1)和for( ; ; )是什么意思?,如何保证这种循环能正常执行?
while(1)相当于while(ture)里面的循环条件一直为真,一直循环下去。
保证这种循环正常执行在后面加一个判断并且为假,就直接跳出循环;或者加一个break;也可以跳出循环,保证这个循环能够正常运行。
for( ; ; )表示为死循环。
因为for后的圆括号中,第一个分号前的内容是执行第一次循环前执行的,第二个分号前的内容是每次执行前都要判断的(如果该处表达式的值为真,那么执行循环体,如果为假,那么就跳出循环体),第二个分号后的内容是每执行完一次循环体后执行的。
在循环体中使用break跳出循环体。
2.一般情况下,设计循环结构时,使用for、while、do while三种语句都可以,并且三种语句可以相互转换,但是,在某些特定情况下,我们应该优先选择某种语句来快速实现循环设计。如果有如下情况:
(1)循环次数已知
(2)循环次数未知,但循环条件在进入循环时明确
(3)循环次数未知,且循环条件在进入循环时未知,需要在循环体中明确
针对上面三种情况,分别采用什么循环语句实现比较好?对每种情况,用我们完成的两次循环结构作业中的题目加以说明。
①用for的循环结构来写。例如:
循环结构(1)中 7-2 统计学生平均成绩与及格人数, 7-3 奇偶分家 7-8 找出最小值,给出7-3的源程序:
#include <stdio.h>
int main(void)
{
int N,i,n,a = 0,b = 0;
scanf("%d",&n);
for(i = 0;i < n;i++)
{
scanf("%d",&N);
if(N % 2 == 0)
{
a++;
}
else
{
b++;
}
}
printf("%d %d",b,a);
return 0;
}
②可以用while和do while的循环结构来写。例如:循环结构(2)中 7-5爬动的蠕虫,循环结构(1)中 7-4 到底是不是太胖了 给出7-5的源程序:
#include <stdio.h>
int main(void)
{
int N,U,D,head=1,time=0;
scanf("%d %d %d",&N,&U,&D);
while(1)
{
head+=U;
time++;
if(head>N)break;
head-=D;
time++;
}
printf("%d",time);
return 0;
}
③可以用do while的循环结构来写。例如:循环结构(2)中 7-1 求给定精度的简单交错序列部分和 7-3 求奇数和,给出7-3的源程序:
#include <stdio.h>
int main()
{
int n = 0, sum = 0;
do
{
scanf("%d", &n);
if (n % 2 == 1)
sum += n;
} while (n > 0);
printf("%d\n", sum);
return 0;
}
3.有如下问题:输入一批学生成绩,以-1作为结束,计算学生的平均成绩。
要求分别用for语句、while语句、do while语句三种循环语句实现,并说明你认为哪种形式更合适?
循环次数未知,且循环条件在进入循环时未知,需要在循环体中明确,所以我觉得用do while写来比较合适。
4.运行下面程序,输入1到10,结果分别是什么?为什么?
(1)
#include<stdio.h>
int main()
{
int n,s,i;
s = 0;
for(i = 1; i <= 10; i++)
{
scanf("%d",&n);
if(n % 2 == 0)
break;
s = s + n;
}
printf("s = %d\n",s);
return 0;
}
输出结果:
(2)
#include<stdio.h>
int main()
{
int n,s,i;
s = 0;
for(i = 1; i <= 10; i++)
{
scanf("%d",&n);
if(n % 2 == 0)
continue;
s = s + n;
}
printf("s = %d\n",s);
return 0;
}
输出结果:
这俩个源程序看上去没什么俩样,但是不同的地方就是第一个用的是break,而第二个用的是continue。结果一个输出1,一个输出25,因为第一个就执行一次s=s+n,而s为0,n为1,当第一次输入1的时候就直接跳出循环就进行s=s+n,所以最后输出1;
而第二个流程图用continue俩控制循环条件,他进行判断后不会跳出而是直接进行下一个,并且把能整除2的数过滤掉,所以最后输出的是25。
(三)实验总结
(1) 题目
7-1 求给定精度的简单交错序列部分和
(2) 流程图
(3) 源代码
#include<stdio.h>
#include<math.h>
int main(void)
{
int dom,flog;
double eps,sum,t;
flog=1;
dom=1;
sum=0;
scanf("%lf",&eps);
do
{
t=flog*1.0/(3*dom-2);
sum+=t;
flog=-flog; /*让这个值改变*/
dom++;
}
while(fabs(t)>eps);
printf("sum = %.6lf",sum);
return 0;
}
(4) 实验分析:
问题1:
第一次写的时候有while的形式是用一下格式:
while(fabs(x) > eps)
{
t=flog*1.0/(3*dom-2);
sum+=t;
flog=-flog; /*让这个值改变*/
dom++;
}
但是输出的结果答案错误,这个问题纠结了很长时间。该程序需要先执行一次然后再进行循环,如果用while的形式就不能保证进行一次,所以该格式不能保证。我们要用do while的格式来写。
do
{
t=flog*1.0/(3*dom-2);
sum+=t;
flog=-flog; /*让这个值改变*/
dom++;
}
while(fabs(t)>eps);
问题2:答案错误
原因:while括号里面的条件判断错误
解决方法:把"<="改成">"。
答案正确:
(5)本题PTA提交列表
(1) 题目:
7-2 猜数字游戏
(2) 流程图
(3) 源代码
#include<stdio.h>
int main()
{
int key, n;
scanf("%d %d",&key,&n); /*输入俩个数*/
int i;
int m;
int flag = 0; /*定义一个数*/
for (i = 1;i <= n;i ++)
{
scanf("%d",&m); /*再次输入一个数*/
if (m < 0)
break;
if (m > key)
printf("Too big\n");
if (m < key)
printf("Too small\n");
if (m == key)
{
if (i == 1)
{
flag = 1; /*为假,跳出*/
printf("Bingo!\n");
break;
}
if (i == 2 || i == 3)
{
flag = 1; /*为假,跳出*/
printf("Lucky You!\n");
break;
}
if (i > 3)
{
flag = 1; /*为假,跳出*/
printf("Good Guess!\n");
break;
}
}
}
if (flag == 0) /*为真,输出*/
printf("Game Over\n");
return 0;
}
(4) 实验分析
错误信息:一开始输入产生随机数,用了数学函数rand(),但是结果输出错误。
原因:理解题意错误,不用函数就可以,直接输入俩个数再进行循环就可以。
需要注意的:循环结束可以用break来实现。在本题需要定义一个量flag=0,如果后面的跟前面所定义的相等就判断为真,如果不相等就判断为假,并且在break的条件下进行跳出进行下一步的运算。
(5)本题PTA提交列表
(1) 题目
7-3 求奇数和
(2) 流程图
(3) 源代码
#include <stdio.h>
int main()
{
int n = 0, sum = 0;
do
{
scanf("%d", &n);
if (n % 2 == 1)
sum += n;
} while (n > 0);
printf("%d\n", sum);
return 0;
}
(4) 实验分析
问题 : 用 if--for的形式输入结果总是部分正确,例如下面的错误源程序
#include <stdio.h>
int main()
{
int n,i,s,sum;
sum=0;
scanf("%d",&n);
i=0;
for(i=0;i<n;i++)
{
scanf("%d",&s);
if(s<0)
{
break;
}
else
{
if(s%2!=0)
{
sum=sum+s;
}
}
}
printf("%d",sum);
}
原因:该程序不能用if for的形式来写,它需要先循环一次,然后再进行循环。给出正确的源程序:
#include <stdio.h>
int main()
{
int n = 0, sum = 0;
do
{
scanf("%d", &n);
if (n % 2 == 1)
sum += n;
} while (n > 0);
printf("%d\n", sum);
return 0;
}
(5)本题PTA提交列表
(四)博客互评
针对移动、淫领四妓夜物 的博客园:
(1).实验总结写的很认真,值得我们学习!老铁,没毛病!继续加油
针对郭玉霖的博客园:
(1).在学习总结的第三个题文字与图片应该空一格,这样看起来比较舒服。
(2).在实验分析的时候应该把问题用截图截下来并且圈出来,这样别人才能知道你哪儿多了条件或者哪儿漏了条件。
针对ShizukaRi的博客园
(1).在改错题应该把错误的源程序给出来并且改正给出正确的。
(2).学习总结只能用很认真来形容,向你学习,可以看出你学的很好。
(3).实验总结的第二个流程图看着有点别扭,希望以后尽量截图好一点,大家能够更好的看清楚。