【2021.12.04】教材代码回顾(3)

本文通过C语言展示了计算阶乘、斐波那契数列、闰年计数、求和、打印九九表和素数等经典算法的实现。讲解了不同类型的循环(for、while、do-while)及其适用场景,并给出了递归解法。同时,文中还指出了常见编程陷阱,强调了循环变量初始化的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第十题:计算a=1/k*(k+1)(注意三种循环的使用)

#include<stdio.h>
int main()
{
	float a=0;
	float k=1;
	int n;
	scanf("%d", &n);
	for (k = 1; k <= n; k++)
	{
		a = 1 / (k * (k + 1))+a;
	}

	do {
		a = 1 / (k * (k + 1)) + a;
		k++;
	} while (k <= n);

	while (k <= n)
	{
		a = 1 / (k * (k + 1)) + a;
		k++;
	}
	printf("%f", a);
	return 0;
}

以上三种循环都可以,注意循环变量的三要素:1.初始值 2.循环条件 3.操作 

第十一题:计算某年份之后n个闰年(循环计数count)

#include<stdio.h>
int main()
{
	int yy, n;
	scanf("%d%d", &yy, &n);
	int count = 0;
	while (count < n)
	{
		yy = yy + 1;
		if ((yy % 4 == 0) && (yy % 100 != 0) || (yy % 400 == 0))
		{
			printf("%d ", yy);
			count++;
		}
	}
	return 0;
}

此代码本身没什么好说的,重点说两个错例:

第一个错例“i”:

#include<stdio.h>
int main()
{
	int yy, n;
	scanf("%d%d", &yy, &n);
	int count = 0;
	int i = 1;
	while (count < n)
	{
		yy = yy + i;
		if ((yy % 4 == 0) && (yy % 100 != 0) || (yy % 400 == 0))
		{
			printf("%d ", yy);
			count++;
		}
		i++;
	}
	return 0;
}

用了两个循环变量 计数的count和i,要注意循环体的特性:上次循环后的其他变量(非循环变量),若未再初始化,会保留原先的值不变,也就是说,每次进循环的时候,yy都会自增1,而不用再用i来增长yy的值,这样反而让yy增长的多了,造成错误

第二个错例(注意):

for循环:循环次数已知的循环,先判断再循环

while循环:循环次数未知的循环,先判断再循环

do—while循环:循环次数未知的循环,先循环一次,再判断

第十二题:计算e的大小:e=1+\sum_{i=1}^{n}\frac{1}{i}!,直到\frac{1}{i}!<10^{-8}

#include<stdio.h>
int main()
{
	float rep = 1e-8;
	float m=1;
	float i = 1;
	float p=1;
	float n = 0;
	while (m > rep)//注意与题里给的符号相反
	{
		p = p * i;
		m = 1 / p;
		n = n + m;
		i++;
	}
	printf("%f", 1.0+ n);
	return 0;
}   //2.718282

注意赋初始值的不同:

1.用来存储的,初始值赋成0

2.用来存储的,初始值赋成1

3.如上面的m,用来进入循环,判断精度的,第一次要进入循环,所以初始值应该是1,而不是0

第十三题:统计以100结束的整数输入流中1 0 -1出现的次数

#include<stdio.h>
int main()
{
	int n;
	int a, b, c;
	a = 0;
	b = 0;
	c = 0;
	scanf("%d", &n);
	while (n != 100)
	{
		switch (n)
		{
		case(0):a++; break;
		case(1):b++; break;
		case(-1):c++;
		}
		scanf("%d", &n);
	}
	printf("%d %d %d", a, b, c);
	return 0;
}

输入数字流:scanf(“%d”,&n);——>一个变量来接收

                                    +

                      循环体中再放一个 scanf(“%d”,&n);

这样操作适用于数字输入即进行处理(进行筛选,加减乘除等),不会全部保存的数字流

第十四题:打印九九表

#include<stdio.h>
int main()
{
	int i;
	int n;
	scanf("%d", &n);
	int j;
	for (i = 1; i<= n; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= i; j++)
		{
			printf("%4d ", j * i);
		}
		printf("\n");
	}
	printf("* ");
	for (i = 1; i <= n; i++)
	{
		printf("%4d ", i);
	}
	return 0;
}

第十五题:打印100以内的素数

#include<stdio.h>
int f(int n)
{
	int i;
	for (i = 2; i <= n / 2; i++)
	{
		if (n % i == 0)
			return 0;
	}
	return 1;
}
int main()
{
	int n=2;
	while (n < 100)
	{
		int res = f(n);
		if (res)
			printf("%d ", n);
		n++;
	}
	return 0;
}

 这里尤其要注意最开始n=2和n=3的时候,由于n/2=1 < i=2 所以不进入此循环,直接跳到return 1

**所以判断素数的时候要用i<n/2,否则这里写i<n,就不好判断2了

第十六题:裴波纳契数列(兔子数列)——对循环体初值的处理//递归

f(n)=f(n-1)+f(n-2)

注意对最开始的三个的处理

#include<stdio.h>
int main()
{
	int n;
	scanf("%d", &n);
	int u, v, w;
	u = 1;
	v = 1;
	w = 2;
	if (n < 3)
	{
		switch (n)
		{
		case(1):printf("%d", w); return 0;
		case(2):printf("%d", a); return 0;
		}
	}
	int i;
	for (i = 3; i <=n; i++)
	{
		w = u + v;
		u = v;
		v = w;	
	}
	printf("%d", w);
	return 0;
}

 

在最开始的时候 ,u,v已经有初始值(1)了,我们循环的是u,v,w,各自向后错一位,之后输出w,也就是说,什么都不做,w也是从2开始的,我们输入的是项数n,所以循环变量的初值必须要考虑循环体实际执行了多少次,如上,n=1或2时,循环体是不用执行的,所以直接输出即可,n>=3时,循环体开始执行,所以i的初值应赋为3(i<=n)或2(i<n),这样i++之后保证只进行一次循环(假设n=3,以后判断循环变量的初始值也可以这样考虑

#include<stdio.h>
int main()
{
	int u, v, w;
	u = 1;
	v = 1;
	int n;
	int i=2;
	scanf("%d",& n);
	if (n < 3)
	{
		printf("1");
		return 0;
	}
	do {
		w = u + v;
		u = v;
		v = w;		
		i++;
	} while (i < n);
	printf("%d", w);
	return 0;
}

 

这里由于do—while循环的特性,只要接触到循环,就会执行一次,所以i的初始值赋成2,这样后面增1之后为3,(i<n)不满足,退出循环(还是在n=3时考虑)

总的来说:i的初始值与循环执行的判断条件之间有多种组合方式,如何匹配?

                  首先,n的值域必须保证连续,不能有断的地方

                 其次,从开始循环的n开始考虑,结合写的循环语句的特性,调整对应的i的初值

 我们再来用递归的方法解决这个问题:

#include<stdio.h>
int fabs(int n)
{
	if (n < 3)
	{
		return 1;
	}
	else
	{
		return fabs(n - 1) + fabs(n - 2);
	}
}
int main()
{
	int n;
	scanf("%d", &n);
	int u, v, w;
	u = 1;
	v = 1;
	if (n < 3)
	{
		printf("1");
	}
	else
	{
		printf("%d",fabs(n));
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值