10讲学会C语言之第四讲:循环结构


前言

大家好,我是卷卷。本节课讲循环结构:for,while和do while。主要包括六个部分:求pi的近似值,统计整数的位数,判断素数,求阶乘和,循环结构编程,作业。(讨论q群号744931080,教程资源在群内)


一、求pi的近似值

例1:在这里插入图片描述
首先对于交错求和,肯定有变量fm表示分母,sign表示符号,sum表示各项和。然后用循环,每轮fm自增2,sign符号取反,sum累加。题目对某项的值有要求,所以还需变量item表示某一项。显然item等于sign/fm。循环用while循环表示比较简洁,结束条件是item的绝对值小于0.0001,最后输出sum即可。重点是while语句。代码:

#include<stdio.h>
#include<math.h>
int main(){
	int fm=1,sign=1;
	double item=1,sum=0;
	while(fabs(item)>=0.0001){
		item=sign*1.0/fm;
		sum+=item;
		sign=-sign;
		fm+=2;
	}
	printf("pi=%.4f",sum*4);
	return 0;
}

前几行要注意一下变量的初始值,然后这里要用到一个绝对值函数fabs()。它表示浮点数的绝对值,要用到math头文件。接下来是while循环,它包括一个圆括号和一对花括号。圆括号里面的内容需要判定真假。如果内容为真,就执行循环体的内容,如果内容为假,就直接结束循环。这个判定和if的道理是一样的。题目要求最后一项的绝对值小于10的-4次,也就是最后一项的绝对值会小于10的-4次,那么之前的绝对值当然就大于等于10的-4次了。我们看一下结果:在这里插入图片描述
这就是用题目的公式计算出的结果。这里其实是用公式无限接近pi,最后一项的绝对值越小,结果越精确。

例2:从键盘输入一批学生的成绩,计算平均成绩并统计不及格学生的人数。首先要有表示成绩的变量grade,统计不及格人数的变量count。计算平均成绩肯定要有总成绩和人数。总成绩用变量total表示。题目未给出总人数,所以设变量num来统计总人数。为了用到while循环,假定输入的成绩以0结束。循环体内输入grade,total累加,再判定grade是否小于60,若是则count累加。最后输出平均成绩和count即可。重点还是while语句。代码:

#include<stdio.h>
int main(){
	int count=0,num=0;
	double grade,total=0;
	printf("输入成绩:");
	scanf("%lf",&grade);
	while(grade>=0){
		total+=grade;
		num++;
		if(grade<60)
			count++;
		scanf("%lf",&grade);
	}
	if(num)
		printf("平均分:%.2f,%d个不及格",total/num,count);
	else
		printf("平均分:0");
	return 0;
}

num是用于统计输入的成绩个数,也就是总人数。当输入的成绩为非负数时,就执行循环。循环体内进行各项操作,然后在下一轮循环之前再次输入grade。如果最后总人数为0,那么就输出0。如果最后总人数不为0,那么就输出平均分和不及格人数。我们来试一下:在这里插入图片描述
这就是运行结果了。

二、统计整数的位数

例3:从键盘读入一个整数,统计该数的位数。例如,输入12534,输出5,输入-99,输出2,输入0,输出1。首先定义整型变量n于输入,count用于统计位数。n的最低位可用模10获得,n除以10向下取整,砍掉最低位,再模10就得到了次低位。以此类推,直到n除到0为止。每除以10就砍掉1位,所以除10的次数即位数。显然需要用到循环,不妨用do while循环。条件是n不为0,每轮循环砍掉一位,之后count自增1即可。循环结束后输出count。本题的重点是do while结构。代码:

#include<stdio.h>
int main(){
	int n,count=0;
	printf("输入一个数:");
	scanf("%d",&n);
	if(n<0)n=-n;
	do{
		n/=10;//砍掉1位 
		count++;
	}while(n);
	printf("包含%d位\n",count);
	return 0;
}

首先如果是负数的话,要做一个取反操作。然后使用do while循环,特别注意:do while后面要跟一个分号!这是与while循环区别之一。每轮循环砍掉1位,然后统计。当砍到零,即n等于0时,所有的位都砍完了,统计也就结束了。我们试一下:在这里插入图片描述
这就是本题的讲解了。

三、判断素数

例4:输入一个正整数m,判断它是否为素数。素数就是只能被1和自身整除的正整数,1不是素数,2是素数。对于素数m,除了1和自身,其他数都不能整除m。也就是除了1和m,其他数i都不能使m模i的结果为0。如果出现不是1和m的数i,使m模i为0,而立即可以断定m不是素数。显然有多个i要检测,所以可利用for循环,i从2到m-1,若m模i为0,则利用break跳出循环。若循环正常结束,则i为素数。比较方便的做法是,判定i是否大于m-1。代码:

#include<stdio.h>
int main(){
	int i,m;
	printf("输入一个数:");
	scanf("%d",&m);
	for(i=2;i<=m/2;i++)
		if(m%i==0)break;
	if(i>m/2&&m!=1)
		printf("是素数\n");
	else
		printf("不是素数\n");
	return 0;
}

首先输入m,i的范围从2到m/2。这个上界是优化过的,可以直接使用。如果中间有能被m整除的数,则立即退出循环。如果循环结束且m不等于1,那么它是素数。否则不是素数。我们试一下:在这里插入图片描述
在这里插入图片描述
这就是本题的讲解了。

四、求阶乘和

例5:在这里插入图片描述
函数由返回类型,函数名,圆括号,圆括号里面的参数,花括号组成。所以自定义函数必须包含这些。显然参数是一个整数,不妨设为int n。由于题目的计算量大,所以返回类型用double。计算阶乘也是比较简单的。定义一个double型变量ans,初始值为1,再用for循环。循环变量i从2到n,ans迭代乘i即可。主函数内用变量sum来累加每一个数的阶乘,用循环来控制该累加什么数的阶乘。题目的结果显然是一个很大的数,可以用百分号e即指数形式输出。本题的重点是定义和调用函数。我们来看一下代码:

#include<stdio.h>
double fact(int n);
int main(){
	int i;
	double sum=0;
	for(i=1;i<=100;i++){
		sum+=fact(i);
	}
	printf("%e\n",sum);
	return 0;
}
double fact(int n){//形式参数 
	int i;
	double ans=1;
	for(i=2;i<=n;i++)
		ans*=i;
	return ans;
}

函数的参数名为n,在下一讲我们会学到,这个n叫做形式参数,它的名字可以任意取定。函数内计算号ans,返回即可。定义了函数以后还需要在上方声明一下,如果不做这个声明,就必须在调用它之前定义。比如说这样:在这里插入图片描述
编译器说fact was not declared in,this scope,这个函数没有在这个范围内声明。也就是编译器不认识这个函数,这是因为编译顺序是从上到下进行的。所以必须将这个函数的声明放在调用它之前,或者直接定义在调用之前。不过为了代码规范,还是建议定义在后面,然后把声明写在开头。主函数体内就比较简单了,每轮循环累加阶乘即可。我们看一下结果:在这里插入图片描述
这就是本题的结果啦。

例6:本题要求使用嵌套循环实现求1到100的阶乘和。本题的大部分内容和上题差不多,区别在于上题是要用函数获得阶乘,本题是直接计算阶乘。显然只是把函数里的过程拿出来即可。由于函数内用了for循环,主函数内也是for循环,所以就形成了二重循环。我们来看一下代码:

#include<stdio.h>
int main(){
	int i,j;
	double sum=0,ans;
	for(i=1;i<=100;i++){
		ans=1;//每轮循环计算i的阶乘 
		for(j=1;j<=i;j++)
			ans*=j;
		sum+=ans;
	}
	printf("%e\n",sum);
	return 0;
}

首先外层循环是一样的,内层循环无非是把函数里的内容照搬了上来。我们看一下结果:在这里插入图片描述
结果和上一题是一样的。

五、循环结构编程

例7:读一批学生的成绩,找出最高分。根据题目要求,可以输入整型变量n,然后输入n个学生成绩。也可以像例2那样有特定的结束标志,这里不妨用前者。显然,我们需要变量grade来表示成绩,max来表示最高分。为了得到最高分,每输入一个成绩,max与它比较,若max较小则max更新为它。显然max必须有一个初始值,那么该值可以是第一个成绩也可以是0,因为成绩最小为0。这里不妨用后者,利用for循环输入,更新max,最后输出max即可。本题的重点显然是如何获得一组数的最大值。代码:

#include<stdio.h>
int main(){
	int n,grade,i,max=0;
	printf("输入学生数:");
	scanf("%d",&n);
	printf("输入%d个学生成绩:\n",n);
	while(--n){
		scanf("%d",&grade);
		if(max<grade)
			max=grade;
	}
	printf("最高分%d\n",max);
	return 0;
}

while循环这里是做了一个简单的写法。当n减到0就退出循环。注意要用后减符号,如果用前减符号,那么当n为1时,会先变成0再判断,这样就会直接退出循环了。循环内首先输入成绩,然后用max和输入的成绩去比较,如果最新输入的成绩比max还要大,max就更新为这个成绩。这点应该没有问题了。最后输出max即可。我们试一下:在这里插入图片描述
这就是运行结果了。因为scanf遇到空格会结束,所以要连续在一行输入,中间以空格分隔即可。

例8:逆序问题。输入一个正整数,将其逆序输出。例如,输入12345,输出54321。本题核心思想和例3一样,都要用到获得数字的各个位的方法。区别是例题3对各个位不作处理,而本题需要输出各个位。例题3的做法是从个位,即最低位开始,刚好符合题目的输出顺序。所以每轮循环输出n模10的结果即可。代码:

#include<stdio.h>
int main(){
	int n;
	printf("输入一个数:");
	scanf("%d",&n);
	printf("各位如下:\n");
	while(n){
		printf("%d ",n%10);//n的最低位 
		n/=10;//砍掉最低位 
	}
	return 0;
}

这里和例题3最大的区别就是要输出n模10的结果。我们测试一下:在这里插入图片描述

例9:求100以内的全部素数,每行输出10个。本题还是求素数,只不过要求100以内的全部素数,每行输出10个。核心思想和例题4一样,都是判定素数。主要区别是判定数从1个扩大到了100个。利用for循环,循环变量从2到100,再按例4那样判定素数即可。代码:

#include<stdio.h>
#include<math.h>
int main(){
	int count=0,i,m,n;
	for(m=2;m<=100;m++){
		n=sqrt(m);//根号m 
		for(i=2;i<=n;i++)
			if(m%i==0)break;
		if(i>n){
			//输出6位,不足补空白符 
			printf("%6d",m); 
			count++;
			if(count%10==0)
				printf("\n");
		}
	}
	printf("\n");
	return 0;
}

首先定义一个循环变量m从2到100,这个没有问题。然后是做一个初始化,这里是做了一个优化的。例3的循环变量的上限是m/2,现在更加优化了。现在的上限是根号m,根号函数是sqrt(),它需要调用math头文件。然后进行素数的判定即可,我相信大家都能理解。最后还要累加素数的个数,因为要每行输出10个,输出10个以后要换行。这里的格式%6d的意思就是输出6位,不足补空白符,而且输出的数是右边对齐的。我们看一下结果:在这里插入图片描述
这就是1到100以内的素数了。

我们看最后的例题,例10:斐波那契数列问题。斐波那契(Fibonacci)序列的特点是头两项均为1,后面任意一项都是其前两项之和。输出斐波那契(Fibonacci)序列的前10项。斐波那契数列问题我想大家不陌生,根据题目,第三项开始,每项都是前两项之和。所以不妨设两个变量,x1和x2代表前两项,x代表当前项。那么x等于x1加x2,若要计算下一项,只需使x1变为x2即下一项的前一项的前一项。再使x2变为x,即下一项的前一项。这样下一项的前两项值都知道了,下一项也就出来了,x再次等于x1加x2。示意图如下:在这里插入图片描述
题目要求序列的前10项,而头两项的值是固定的,所以只需利用for循环,循环8次即可。每次循环输出x,即当前项。本题的重点是迭代保存思想。代码:

#include<stdio.h>
int main(){
	int i,x1,x2,x;
	x1=1;
	x2=1;
	printf("%6d%6d",x1,x2);
	for(i=1;i<=8;i++){
		x=x1+x2;
		printf("%6d",x);
		x1=x2;
		x2=x;
	}
	printf("\n");
	return 0;
}

首先固定好前两项,然后开始循环。每轮循环一开始就计算当前项。然后更新x1和x2,则下一轮循环的x1就是本轮循环的x2,下一轮循环的x2就是本轮循环的x。这就是迭代保存思想。我们看一下结果:在这里插入图片描述
这就是斐波那契数列的前10项了。好了,这就是例题的全部讲解了。

六、作业

作业是10个例题加4道练习题,总共14道题。练习1和2:在这里插入图片描述
第一题是求一系列正整数中奇数的和,很简单,我想大家肯定都会。第二题其实也不难,求的是十进制整数。所以也不难算,比如说11,那么刚开始是1那么1就要等于0乘以10加上1。如果是3个1,那么在11的基础上再乘以10,加1即可。这样我想大家应该能明白了。这里显然用了迭代的形式,就不做赘述了。练习3和4:在这里插入图片描述
第三题的输入一显然包括0。这里其实要用到三个变量:第一个变量是经过距离d,第二个变量是下落高度h1,第三个变量是反弹高度h2。刚开始的时候如果初始高度h等于0,那么显然两个高度都为0。如果初始高度不为0,那么要分两种情况。第一次反弹和第一次反弹以后。第一次下落时,下落高度h1等于h,经过距离d也等于h,反弹高度h2等于h/2,也就是下落高度的一半。从第二次开始,下落高度就要等于上次反弹高度,也就是h1=h2。然后经过距离再加下落高度,即d += h1。最后反弹高度等于本次下落高度的一半,即h2=h1/2。之后每一次都这样操作。这就是本题的核心思想了,有了这个,本题也不难了。第四题要注意每个星号后跟一个空格。我们观察星号数量:在这里插入图片描述
刚开始是1,然后是3,然后是5。那么星号数量每次是加2的。那么空格数的规律又是什么呢?我们需要看一下原题,通过数原题的空格数来分析。原题的图案可以数出空格来,第一行是6个,第二行是4个,第三行是2个。也就是刚开始空格数是n-1个,然后每轮循环减少2个。这样的话就比较好做了,在星号的数量达到最多或空格的数量达到最少的时候它们又开始各自以相反的方向变化。星号每轮减少2个,空格每轮增加2个。也就是星号数量达到最多的时候,空格数量从1开始,每轮增加2个。星号数量从n-2开始每轮减少2个。本题可以用一个循环,也可以用两个循环。关键在于控制好星号数和空格数这两个变量。这里还是要提醒一下,每个星号后跟一个空格。好了,这就是本讲的全部内容了,希望大家认真做作业。我们下讲见!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值