for用于控制一些需要重复执行的代码
用法:
-
for(表达式1;表达式2;表达式3) 语句;
-
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,使
i
的初始值为1 - 看表达式2,此时
i
的值为1,满足i<=4
- 执行循环体
- 执行表达式3,使
i
的值加1,执行完表达式3后此时i
的值为2
第二次:
- 看表达式2,此时
i
的值为2,满足i<=4
- 执行循环体
- 执行表达式3,使
i
的值加1,执行完表达式3后此时i
的值为3
第三次:
- 看表达式2,此时
i
的值为3,满足i<=4
- 执行循环体
- 执行表达式3,使
i
的值加1,执行完表达式3后此时i
的值为4
第四次:
- 看表达式2,此时
i
的值为4,满足i<=4
- 执行循环体
- 执行表达式3,使
i
的值加1,执行完表达式3后此时i
的值为5
第五次:看表达式2,此时i
的值为5,已经不满足i<=4
了,不用执行循环体,for循环结束。
其它补充:
-
表达式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; }
-
-
-
for和while其实是等价的
for(表达式1;表达式2;表达式3) { 语句A; 语句B; ... } 可以改写成下面代码: 表达式1; while 表达式2 { 语句A; 语句B; ... 表达式3; }
-
如果某些代码要一直运行,不用停下来,可以这样写
for(;;) { ... } 用while就是这样写: while(1) { ... }
-
for循环可以嵌套
for(表达式1;表达式2;表达式3) { for(表达式4;表达式5;表达式6) { ... } }
- 先执行表达式1,判断满不满足表达式2,满足就执行循环体。
- 循环体里面也是个for循环,所以接着执行表达式4,判断满不满足表达式5,满足就执行第二个for的循环体。执行完第二个for的循环体后执行表达式6,然后看满不满足表达式5,满足就继续执行第二个for的循环体,一直到不满足表达式5,第二个for循环才算结束。
- 第二个for循环结束,就执行表达式3,然后看表达式2满不满足,满足就继续执行第一个for的循环体,也就是第二个for循环。一直到不满足表达式2了,这整个循环才结束。
-
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;
}
- 在本例中,for循环里面的
i
不要定义成浮点型- 由于浮点型的精度会不够准确,在第100次循环的时候
i
自加后值可能不是准确的100(可能是100点多),这样会导致不满足i<=100
,从而导致循环直接结束。 - 第一点不仅限于第100次循环,可能在其它次循环的时候也会出现,比如第三次循环,
i
自加后值也可能不是精准的3,导致不满足i<=100
而使循环结束。
- 由于浮点型的精度会不够准确,在第100次循环的时候
- 如果语句
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;
}