前面我们讲的是单个 for 循环的使用,最后再跟大家讲一下多层 for 之间的嵌套使用。虽说是多层,事实上 for 循环嵌套的层数也不能太多。通常为两个 for 循环的嵌套,超过两个的极少使
与单个 for 循环相比,多个 for 循环的嵌套在逻辑上更复杂一点,但并不难懂。直接给大家写一个程序:
# include <stdio.h> int main(void) { int i, j; for (i=0; i<4; ++i) { printf("问世间情是何物, 直教生死相许\n"); for (j=0; j<3; ++j) { printf("两情若是久长时, 又岂在朝朝暮暮\n"); } } return 0; }
输出结果是:
问世间情是何物, 直教生死相许
两情若是久长时, 又岂在朝朝暮暮
两情若是久长时, 又岂在朝朝暮暮
两情若是久长时, 又岂在朝朝暮暮
问世间情是何物, 直教生死相许
两情若是久长时, 又岂在朝朝暮暮
两情若是久长时, 又岂在朝朝暮暮
两情若是久长时, 又岂在朝朝暮暮
问世间情是何物, 直教生死相许
两情若是久长时, 又岂在朝朝暮暮
两情若是久长时, 又岂在朝朝暮暮
两情若是久长时, 又岂在朝朝暮暮
问世间情是何物, 直教生死相许
两情若是久长时, 又岂在朝朝暮暮
两情若是久长时, 又岂在朝朝暮暮
两情若是久长时, 又岂在朝朝暮暮
其实,多层 for 循环嵌套的执行过程与单个 for 循环的执行过程是一模一样的。多层 for 循环的嵌套只不过是将单个 for 循环大括号中的“语句”换成了 for 循环而已。
下面看看上面程序中两个 for 循环嵌套是怎么执行的。
1) 首先求解表达式 1,即给变量 i 赋初值,i=0;表达式 1 只执行这一次,下面都不会再执行了。
2) 然后求解表达式 2,即 0<4 成立,则执行 for 循环中的内嵌语句:
printf("问世间情是何物, 直教生死相许\n"); for (j=0; j<3; ++j) { printf("两情若是久长时, 又岂在朝朝暮暮\n"); }首先 “printf("问世间情是何物,直教生死相许\n")”,然后执行内部 for 循环,对这个 for 循环再次应用“单个 for 循环”的执行过程:
- 首先求解表达式 1,即给变量 j 赋初值,j=0。
- 然后求解表达式 2,即 0<3 成立,则执行 for 循环中的内嵌语句,即 “printf("两情若是久长时,又岂在朝朝暮暮\n");”。
- 然后执行表达式 3,变量 j 自加 1,即变量 j 由 0 变为 1。
- 然后求解表达式 2,即 1<3 成立,则执行 for 循环中的内嵌语句,即“printf("两情若是久长时,又岂在朝朝暮暮\n");”。
- 然后执行表达式 3,变量 j 自加 1,即变量 j 由 1 变为 2。
- 然后求解表达式 2,即 2<3 成立,则执行 for 循环中的内嵌语句,即“printf("两情若是久长时,又岂在朝朝暮暮\n");”。
- 然后执行表达式 3,变量 j 自加 1,即变量 j 由 2 变为 3。
- 然后求解表达式 2,即 3<3 不成立,则内部的循环结束。对内部的 for 而言循环是结束了,但对外部的 for 而言,“for 循环的执行”过程才执行到表达式 3。
4) 然后再求解表达式 2……
……
就这样一直循环下去,直到外层循环结束,整个循环才结束。
总之,不管是单个 for 循环还是多个 for 循环的嵌套,它们的执行过程是一样的。只不过如果是“多个 for 循环的嵌套”,则其执行过程也是嵌套的。
for循环嵌套编程练习
1) 求出 1!+2!+3!+…+n!的和。对于这个程序前面用一个for编程也可以实现,但是逻辑性太强,现在再用for循环嵌套编程实现一下:
# include <stdio.h> int main(void) { int n = 0; //存储1!+2!+3!+…+n!中n的值 int i = 0, j = 0; //循环变量 int m = 1; //用于计算每个数的阶乘 unsigned long sum=0; /*阶乘的值往往很大, 定义成long型。虽然如此, 下面输入的n的值也不能太大, 不然long也放不下*/ printf("请输入n的值:"); scanf("%d", &n); for (i=1; i<=n; ++i) { for (j=1; j<=i; ++j) //求一个数的阶乘 { m = m*j; } sum = sum + m; //求完之后就立即把它加到sum中 m = 1; } printf ("sum = %ld\n", sum); return 0; }输出结果是:
请输入n的值:10
sum = 4037913
我们看到 n 的值仅为 10 结果就这么大,要再大点 long 类型肯定是存放不了的。此外,有人可能会纠结这样的问题,程序开头定义那么多变量,可是我写的时候怎么知道后面要用到哪些变量呢?其实,这些变量都不是刚开始写程序的时候就定义的,大多数情况下都是“若刚开始知道定义哪些变量那么就定义上,如果不知道那就不定义,等到后面需要用再回到前面进行定义”,这才是正常的逻辑。
2) 求出用 50元、20元 和 10元换算 100元有几种方式?
思路:用穷举法, 将所有可能的情况都列出来, 用 for 循环可以实现穷举
分析:100 元单用 50 换算, 最多需要两张;用 20 元换算, 最多需要五张;用 10 元换算最多需要十张
# include <stdio.h> int main(void) { int w, e, s; //w代表wushi;e代表ershi;s代表shi for (w=0; w<=2; ++w) { for (e=0; e<=5; ++e) { for (s=0; s<=10; ++s) { if (100 == 50*w+20*e+10*s) { printf("%d %d %d\n", w, e, s); } } } } return 0; }输出结果是:
0 0 10
0 1 8
0 2 6
0 3 4
0 4 2
0 5 0
1 0 5
1 1 3
1 2 1
2 0 0
3) “百钱买百鸡”是中国古代一个著名的枚举法题目。所谓枚举就是将所有可能的情况全部列出来的意思。for 循环嵌套是实现枚举的一种手段,上面的换算也是一种枚举。假设公鸡 5 元一只,母鸡 3 元一只,小鸡 1 元 3 只,现在给你 100 元,要你买回 100 只鸡,求出公鸡、母鸡、小鸡分别为多少只。
# include <stdio.h> int main(void) { int x, y, z; //x、y、z 分别表示公鸡、母鸡、小鸡 for (x=0; x<20; ++x) { for (y=0; y<33; ++y) { z = 100 - x - y; //小鸡也可以用循环,但是能用二层循环解决的就不要用三层。 if ((0 == z%3) && (100 == 5*x + 3*y + z/3)) //将 0==z%3 放前面更好,因为 && 是“短路与”,前面不成立后面就不会执行了,所以把计算量小的放前面。 { printf("x = %d, y = %d, z = %d\n", x, y, z); } } } return 0; }输出结果是:
x = 0, y = 25, z = 75
x = 4, y = 18, z = 78
x = 8, y = 11, z = 81
x = 12, y = 4, z = 84