C语言中的for循环

for用于控制一些需要重复执行的代码

用法:

  1. for(表达式1;表达式2;表达式3)
        语句;
    
  2. for(表达式1;表达式2;表达式3)
    {
        语句A;
        语句B;
        ...
    }
    

用一个小例子说一下fo循环执行的顺序
计算1+2+3+4的值

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

在这个for循环中,运行顺序是:
第一次:

  1. 先执行表达式1,使i的初始值为1
  2. 看表达式2,此时i的值为1,满足i<=4
  3. 执行循环体
  4. 执行表达式3,使i的值加1,执行完表达式3后此时i的值为2

第二次:

  1. 看表达式2,此时i的值为2,满足i<=4
  2. 执行循环体
  3. 执行表达式3,使i的值加1,执行完表达式3后此时i的值为3

第三次:

  1. 看表达式2,此时i的值为3,满足i<=4
  2. 执行循环体
  3. 执行表达式3,使i的值加1,执行完表达式3后此时i的值为4

第四次:

  1. 看表达式2,此时i的值为4,满足i<=4
  2. 执行循环体
  3. 执行表达式3,使i的值加1,执行完表达式3后此时i的值为5

第五次:看表达式2,此时i的值为5,已经不满足i<=4了,不用执行循环体,for循环结束。

其它补充:

  1. 表达式1、2、3的补充:

    • 表达式1

      • 用于设置初始条件,就是设定变量的初始值。如果在for循环外面就已经设好值,这里可以忽略不写

        int i = 0;
        for(;...;...)
        {
            ...
        }
        
      • 在一些编译器里也可以直接在这里新定义一个或多个变量。但要注意在这里新定义的变量仅限在这个for循环里使用,在外面用不了:

        for(int i = 0;...;...)
        {
            ...
        }
        print("i=%d",i);//这里会报错,提示i未定义。
        
      • 在for这个循环的整体中,表达式1只会执行一次

    • 表达式2

      • 用于设置循环的条件,就是用来判定是否要继续循环
      • 在执行循环体(就是for后面大括号的内容)前都会先执行表达式2,看是否满足
    • 表达式3

      • 调整控制循环的变量

      • 循环体执行完后,表达式3才会执行。

      • 如果表达式3循环体里面写了,则表达式3就能省略不写

        #include <stdio.h>
        int main(void)
        {
        	int i = 0;
        	int sum = 0;
        	for(i=1;i<=4;)//表达式3空着
        	{
        		sum = sum+i;
                i++;//表达式3写在这里也行
        	}
        	printf("sum=%d\n",sum);
        	return 0;
        }
        
  2. for和while其实是等价的

    for(表达式1;表达式2;表达式3)
    {
        语句A;
        语句B;
        ...
    }
    可以改写成下面代码:
    表达式1;
    while 表达式2
    {
        语句A;
        语句B;
        ...
        表达式3;
    }
    
  3. 如果某些代码要一直运行,不用停下来,可以这样写

    for(;;)
    {
        ...
    }while就是这样写:
    while(1)
    {
        ...
    }
    
  4. for循环可以嵌套

    for(表达式1;表达式2;表达式3)
    {
        for(表达式4;表达式5;表达式6)
        {
            ...
        }
    }
    
    1. 先执行表达式1,判断满不满足表达式2,满足就执行循环体。
    2. 循环体里面也是个for循环,所以接着执行表达式4,判断满不满足表达式5,满足就执行第二个for的循环体。执行完第二个for的循环体后执行表达式6,然后看满不满足表达式5,满足就继续执行第二个for的循环体,一直到不满足表达式5,第二个for循环才算结束。
    3. 第二个for循环结束,就执行表达式3,然后看表达式2满不满足,满足就继续执行第一个for的循环体,也就是第二个for循环。一直到不满足表达式2了,这整个循环才结束。
  5. for循环嵌套如果写成这样:

    for(表达式1;表达式2;表达式3)
        for(表达式4;表达式5;表达式6)
            语句A;
            语句B;
    
    上面的代码等价于下面的代码:
    for(表达式1;表达式2;表达式3)
    {
        for(表达式4;表达式5;表达式6)
        {
            语句A;
        }
    }
    语句B;
    

一些小例子

例一
求1 + 1/2 + 1/3 +…+ 1/100的和

#include <stdio.h>
int main()
{
	float sum = 0;
	for(int i=1; i<=100; i++)
	{
		sum = sum + 1/(float)i;
		//也可以用最简单的写法:sum = sum + 1.0/i;
	}
	printf("1 + 1/2 + 1/3 +...+ 1/100的和是:%f\n",sum);
	return 0;
}
  1. 在本例中,for循环里面的i不要定义成浮点型
    • 由于浮点型的精度会不够准确,在第100次循环的时候i自加后值可能不是准确的100(可能是100点多),这样会导致不满足i<=100,从而导致循环直接结束。
    • 第一点不仅限于第100次循环,可能在其它次循环的时候也会出现,比如第三次循环,i自加后值也可能不是精准的3,导致不满足i<=100而使循环结束。
  2. 如果语句sum = sum + 1/(float)i写成sum = sum + 1.0/i,可能会有警告,因为1写成1.0,系统默认这个1.0的数据类型是double,计算的结果也是double类型,而sum是float类型,把一个double类型的值赋给float类型的变量,精度可能会有损失。

例二
输入两个正整数,求它们的最大公约数(Greatest Common Divisor(GCD))和最小公倍数(Least Common Multiple)

这里求最大公约数用辗转相除法(欧几里得算法),就是以除数和余数反复做除法运算,当余数为0时,当前算式中的除数即为最大公约数。

例:求 1997和615的最大公约数:
1997 ÷ 615 = 3(余 152)
615 ÷ 152 = 4(余7)
152 ÷ 7 = 21(余5)
7 ÷ 5 = 1(余2)
5 ÷ 2 = 2(余1)
2 ÷ 1 = 2(余0)
当余数为零的时候,这条式子的除数就是最大公约数,因此1997和615的最大公约数为1。

求两个数的最小公倍数很简单,就是把两数相乘,所得的积再除以最大公约数,结果就是最小公倍数。

#include <stdio.h>
int main(void)
{
	int data1 = 0;
	int data2 = 0;
	int temp = 0;
	puts("请输入两个正整数:");
	scanf("%d%d",&data1,&data2);
	if(data1<data2)
	{
		temp = data2;
		data2 = data1;
		data1 = temp;
	}//保证data1比data2大
	for(int a=data1,b=data2;;)
	{
		if(a%b==0)
		{
			printf("%d和%d的最大公约数是:%d,最小公倍数是:%d\n",data1,data2,b,data1*data2/b);
			break;
		}
		temp = a%b;
		a = b;//更新a的值为当前算式的除数,下次循环用来当做被除数
		b = temp;//更新b的值为当前算式余数,下次循环用来当除数
	}
	return 0;
}

例三
输入一个正整数,判断它是不是水仙花数

水仙花数(Narcissistic number)是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身。
例如:13 + 53+ 33 = 153。
在十进制中,三位的水仙花数共有4个:153,370,371,407;

(虽然网上很多答案了,还是附上我自己写的代码和思路)

判断某个数是不是水仙花数,就要知道每个位上的数字的3次幂之和等不等于它本身

以输入数字1234为例:

为了取到每个位上的数字,我的方法是让这个数字除以10,得到的商再继续除以10,一直到商为0,每次计算得到的余数就是每个位上的数:
1234 / 10 = 123 … 4(这里的余数4就是个位上的数)
123 / 10 = 12 … 3(余数3是十位上的数)
12 / 10 = 1 … 2(余数2是百位上的数)
1 / 10 = 0 … 1(余数1是千位上的数)

因为输入的数可能会有很多位,所以用一个for循环语句来实现"一直除以10"这个动作,直到商为0。

用pow(a,b)函数来求一个数的幂次方,a是底数,b是次方。配合取余符号%,就可以计算每个位上的3次方的数

#include <stdio.h>
#include <math.h>//pow()函数在这个头文件定义
int main(void)
{
	int data = 0;
	int result = 0;//用于计算“data”每个位上的数字的3次幂之和
	puts("请输入一个正整数:");
	scanf("%d",&data);
	if(data != 1)//尽管1满足“1^3=1”,但不是三位数,也就不是水仙花数,先排除这个特殊情况。
	{
		for(int a = data;;)
		{
			result = result + pow((a%10),3);
			a = a/10;//用商替换掉a的值,准备下一次用来除以10
			if(a == 0)//如果商为0,就退出for循环
			{
				break;
			}
		}
	}
	if(result == data)
		printf("%d是水仙花数\n",data);
	else
		printf("%d不是水仙花数\n",data);
	return 0;
}

输入1234
第一次循环,a=1234,除以10取余,计算余数的三次方(pow((a%10),3)),加到result中,然后更新a的值为1234除以10的商;
第二次循环,a=123,除以10取余,计算余数的三次方,加到result中,再更新a的值为123除以10的商;
第三次循环,a=12,除以10取余,计算余数的三次方,加到result中,再更新a的值为12除以10的商;
第四次循环,a=1,除以10取余,计算余数的三次方,加到result中,再更新a的值为1除以10的商,
此时a的值为0了,退出for循环,看result的值等不等于1234,等于就是水仙花数,不等于就不是水仙花数

例四
求斐波那契数列的第n项

斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89…,这个数列从第3项开始,每一项都等于前两项之和

#include <stdio.h>
int main(void)
{
	int n;
	int a=1;
	int b=2;
	int c;
	puts("请输入你想求斐波那契数列的第几项:");
	scanf("%d",&n);
	if(n == 1)
	{
		c = 1;
	}
	else if(n == 2)
	{
		c = 2;
	}
	else
	{
		for(int i=3; i<=n; i++)
		{
			c = a + b;
			a = b;
			b = c;
		}
	}
	printf("斐波那契数列的第%d项是:%d",n,c);
	return 0;
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值