史上最强C语言教程—-分支和循环(4)
目录
3.2 for循环
我们已经知道了while循环,但是我们为什么还要一个for循环呢?
首先来看看for循环的语法:
3.2.1 语法
for(表达式1; 表达式2; 表达式3) 循环语句;
表达式1
表达式1为初始化部分,用于初始化循环变量的。我们称之为条件初始化。
表达式2
表达式2为条件判断部分,用于判断循环时候终止。我们称之为条件判断。
表达式3
表达式3为调整部分,用于循环条件的调整。我们称之为条件更新。
循环语句
每一次进入循环条件判断通过后需要执行的语句,如果想要执行多条语句需要用{}将我们需要要执行的多条语句括起来形成一个语句块。
从上面可以看出:for语句与while语句与do while语句不同的地方在于它的条件初始化、条件判断、条件更新更为紧凑,都在同一个()内,方便我们进行后续的修改,而do while 与while语句这三个部分相隔就比较远,不便于进行修改,也因此我们使用for循环的频率更高。
下面给大家举个例子吧,帮助大家了解一下for循环语句的使用!
使用for循环在屏幕上打印1~10的数字。
#include <stdio.h> int main() { int i = 0; //for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/) for (i = 1; i <= 10; i++) { printf("%d ", i); } return 0; }
3.2.2 break与continue在for循环中
通过对比while和do while,它们在使用continue和break时,唯一的区别点在于for在执行continue后进入的是条件更新语句,而while与do while则进入条件判断语句,然后进入下一次循环,而使用break时两者都一样,都是跳出循环。
3.2.3 for语句的循环控制变量
建议:
1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。原因就是左闭右开可以清楚的看出循环次数。(当然,这并不是强制的,有时也应该根据使用场景进行灵活变通)
下面给出一个例子,帮助大家理解第二条建议:
int i = 0; //前闭后开的写法 for(i=0; i<10; i++) {} //两边都是闭区间 for(i=0; i<=9; i++) {}
观察上面两个例子,前者采用的是左闭右开,后者采用的是完全闭区间,而前者很容易就能看出该循环的循环次数为10次,即10减去0,而后者则需要9-0+1才能得到真正的循环次数,虽然左闭右开不是强制规定的,但却是众多程序员所极力推荐的,因为这样写的话将会有更好的阅读体验,也有助于后续的调试。
3.2.4 一些for循环的变种
(1)死循环
#include <stdio.h> int main() { //代码1 for (;;) { printf("hehen"); } //for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题。
条件初始化,条件判断,条件更新都是可以根据具体需要进行省略的,但我们往往并不推荐进行省略,因为加上之后程序将有更加良好的阅读体验,而且完全省略后将其写在其它地方的话,相当于我们也放弃了for循环的真正作用,即抛弃了我们使用for循环的初衷,所以并不推荐大家去省略。
注意:当条件初始化、条件判断、条件更新都省略后,程序将进入死循环。
(2)两段有趣的代码
//代码1 #include<stdio.h> int main() { int i = 0; int j = 0; int count = 0; //这里打印多少个hehe? for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { printf("hehen"); count++; } } printf("%dn", count); }
//代码2 #include<stdio.h> int main() { int i = 0; int j = 0; int count = 0; //如果省略掉初始化部分,这里打印多少个hehe? for (; i < 10; i++) { for (; j < 10; j++) { printf("hehen"); count++; } } printf("%dn", count); }
在这两段代码中,用count进行保存hehe输出的次数,执行程序,程序的执行结果分别是100、10。为什么会发生这种结果呢?下面我来给大家简单分析一下!
先看这两段代码,唯一的区别就是后者在二层循环中for的括号中省略了条件初始化语句,这会造成什么影响呢?我们首先看第一段代码:首先赋初值i=0;然后进行条件判断,i<10,进入到了第二层for循环,第二层for循环首先对j进行赋值操作,然后进行条件判断j<10,输出hehe,count变为1,然后进行条件更新,接着又重新进入了条件判断,依次循环,内层循环结束后将跳出。
此时已经输出了10个hehe,然后进入了外层循环的条件更新,i++,i变为1,i<10,进入了第二次的内层循环。
由于此时存在条件初始化语句j又被赋值为0,重复上面的过程,又再次输出了10个hehe,继续重复上面的循环,最终将打印10*10=100个hehe。
看代码2,代码2中由于不存在条件更新语句,所以在内层循环执行完一次之后,当i赋值为1后进入第二次内层循环时,此时j的值未曾改变,依旧是10,所以内层循环在条件判断时直接跳出,所以最终只能打印10个hehe。
总的来说,就是代码2相比代码1少了条件初始化语句,所以在循环过后j的值没有改变,依旧是上一次循环结束后的值,即10,所以在内层循环条件判断时直接不满足跳出。
大家看到这相信大家也明白了,给大家展示这段代码的意义就是希望大家不要对for语句中的三个部分进行省略!因为错误的省略有时会带来严重的错误,使我们的代码无法实现我们想要它真正实现的功能。
(3) 多个变量控制循环
#include<stdio.h> int main() { //代码4-使用多余一个变量控制循环 int x, y; for (x = 0, y = 0; x < 2 && y < 5; ++x, y++) { printf("hehen"); } return 0; }
条件运行结果大家也看到了,最终只打印了两个hehe,为什么会这样呢?因为当x=2时就不满足条件判断语句(判断满足的条件是x<2并且x<5)了,就跳出了循环,此时只进行了2次循环,打印出了两个hehe。
这个地方呢,给大家拓展一下,如果我们把&&改为||会怎么样呢?答案是会执行5次循环,因为如果当x =5时就不满足条件判断语句(判断满足的条件是x<2或者x<5满足一个条件即可)了,就跳出了循环,此时只进行了5次循环,打印5个hehe。
注意:
很多同学喜欢这样写for循环语句:
#include<stdio.h> int main() { for (int i = 0; i < 10; i++) { pritnf("hehen"); } return 0; }
这样写呢,就是进行条件初始化的时候进行条件定义,这样写不是不行,但是此时要注意i的作用域,即只在这个for循环语句内有效,当然,我们并不推荐这种写法,我们推荐的是下面这种写法:
#include<stdio.h> int main() { int i = 0; for (i = 0; i < 10; i++) { pritnf("hehen"); } return 0; }
为什么会推荐这种写法呢?因为我们后面可能会对i进行判断,判断这个循环是否完全完成,或者判断是否因为某些异常原因而终止了,这种代码相对于上面第一种代码更为实用,应用范围更广,所以推荐大家使用第二种!