计算机小白的成长历程——分支与循环(4)

大家好,很高兴又能和你们见面。在上一篇的内容中我们探讨了while语句以及break和continue在while语句中的用法,今天的内容咱们将继续探讨第二个循环语句——for语句。

for语句

1.for循环的语句结构

在开始for循环之前,我们先来探讨一个问题,为什么在C语言中已经有while循环了,还要加入for循环呢?我们来对比一下二者的语句结构:

代码语言:javascript
复制
//while语句结构
对象语句;//循环对象的初始化;
while (条件语句;)//对象是否进入循环的判断;
{
	执行语句;
	递进语句;//调整对象,使其避免死循环;
}

//for语句结构
for (对象语句; 条件语句; 递进语句)
{
执行语句;
}

我们可以从两者的结构看到,while语句的与对象有关的三要素是分开的,这会有一个缺陷,如果这三者间存在很多很多的内容,那就会使它们离得很远,要是在编写的过程中,我想要修改其中一个内容,寻找起来会比较麻烦,而且还有可能出现像上一篇中介绍continue时while陷入的死循环,那有朋友可能就会说,我直接把它们放一起好了,这里是不是就像我们for语句结构一样了,直接将它们三者放在一个括号里,这样想修改时,只需要找到for语句这一行就能随时修改了,会比较方便。既然已经说到这里了,那我们就继续探讨一下for循环的语句流程吧:

2.for循环的语句流程:

计算机小白的成长历程——分支与循环(4)_for语句

从流程图中我们可以看到,程序在进入for循环后执行顺序是1->2->3->4->2->3->4……后面2/3/4一直按照顺序去循环,直到判断为假,才会结束循环,大家还记得while的语句流程吗?

计算机小白的成长历程——分支与循环(4)_for循环_02

这里我们把它细化了一下,大家来对比一下两者异同点:

3.for循环与while循环的比较

相同点:

1.都是先由对象语句到判断语句再开始选择进入循环内还是循环外的执行语句,最后由执行语句到递进语句后再回到判断语句;

2.在判断语句中都是进行真假判断,遵循0为假非0为真的逻辑进行判断,结果为0,执行循环外的语句,结果为非0,执行循环内的语句;

3.在执行语句中遇到break时,都是直接跳到循环外的执行语句;

不同点:

1.进入循环的节点不同,for语句是在对象语句前就进入循环了,而while循环是在对象语句后再进入循环;

2.语句执行的逻辑不同,for循环的执行逻辑是判断->执行->递进按照此逻辑顺序不断重复,而while循环则会根据递进语句的位置而改变逻辑——递进语句在执行语句前,则是判断->递进->执行递进语句在执行语句后,则是判断->执行->递进

3.在执行语句中,for语句遇到continue时是跳到递进语句,再到判断语句,其逻辑顺序为判断->执行->continue->递进->判断而while循环则是直接到判断语句,根据递进语句位置的不同其逻辑顺序也会有些许差异:

(1)递进语句在执行语句前,则是判断->递进->执行->continue->判断

(2)递进语句在执行语句后,则是判断->执行->continue->判断

由此我们可以看出,在语句的使用上for循环确实比while循环方便很多,因为for循环的逻辑顺序使它不会陷入死循环中,而while循环则会因为递进语句的位置不同导致其可能会陷入死循环。

4.for循环的循环控制变量

在for循环中变量的写法有两种:

代码语言:javascript
复制
//前闭后开的写法
for (int i = 0; i < 10; i++)
{
执行语句;
}
//前闭后闭的写法
for (int i = 0; i <= 9; i++)
{
执行语句;
}

这两种写法都对,可以依照个人的喜好自行选择,但是第一种相比于第二种来说,多了一些意义,在第一种前闭后开的写法中判断语句i<10,这里的10既是我们此时for语句的循环次数,也是执行语句的执行次数,更是变量i的个数,我们可以从这种写法中直接判断出for语句在正常运行时需要执行多少次。当然也不一定适用于所有情况,这个写法的问题各位朋友可以自行斟酌。

这里有一点需要注意,我们的变量尽量不要在循环体内去修改,防止变量失去for循环的控制,从而进入死循环。什么意思呢?下面我们通过代码来进一步理解:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<string.h>

int main()
{
for (int a = 0; a < 10; a++)
{
if (a = 5)
{
printf("haha%d\n", a);
continue;
}
printf("haha%d\n", a);
}
return 0;
}

我们来执行一下,看看它会发生什么结果:

计算机小白的成长历程——分支与循环(4)_for循环_03

从运行结果中我们可以看到,此时循环并未结束,一直打印的是a=5的情况,为什么会这样呢?这里我们来分析一下这个代码中的选择语句if(a= 5),此时if中使用的操作符时“=”不是“==”,“=”的意思是赋值,此时的语句意思是将5赋值给a,在回到判断语句语句时一直重复的是6<10判断为真,进入循环,在这里我们通过这一句改变了变量的值,从而导致变量失去了for的控制,并不能很好的进行递进;而操作符“==”的意思是判断相等,这里只起一个判断作用,并未改变变量的值,我们看一下它的打印结果:

计算机小白的成长历程——分支与循环(4)_for循环_04

这里我们可以看到,正常打印,并未影响for语句对变量a的控制。从这个例子中我们能得出结论:

如果在循环体内改变了循环变量可能会导致循环变量失去for的控制,建议尽量不要在循环体内改变循环变量。

5.一些for循环的变种

(1)变种1——省略变量、判断、递进:

在for循环中,我们是可以省略变量、判断和递进的,但是,for循环的判断部分如果被省略了,那判断条件就是恒为正。下面我们来分别探讨这几个问题:

正常编写for语句:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<string.h>

int main()
{
int a = 0, b = 0, c = 0;
for (a = 0; a < 5; a++)
{
c++;
for (b = 0; b < 5; b++)
{
printf("hehe%d\n", c);
c++;
}
printf("%d\n", c);
}
return 0;
}

这里我们看一下,它会打印多少个hehe:

计算机小白的成长历程——分支与循环(4)_for循环_05

总共是可以打印25个呵呵,接下来我们开始依次省略变量、判断、递进。

省略变量:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<string.h>

int main()
{
int a = 0, b = 0, c = 0;
for (; a < 5; a++)
{
c++;
for (; b < 5; b++)
{
printf("hehe%d\n", c);
c++;
}
printf("%d\n", c);
}
return 0;
}

大家可以猜一下我们会打印几个hehe?大家都想好了吗?下面我们就来揭晓答案:

计算机小白的成长历程——分支与循环(4)for循环_06

总共打印了5个,和大家设想的结果是否一致呢?下面我们就来看一下在b=5之后循环内发生了什么:

计算机小白的成长历程——分支与循环(4)#include_07

此时b=5,跳出了第二个for循环;

计算机小白的成长历程——分支与循环(4)_#include_08

这里我们可以看到在跳出第二个for循环后将c打印了出来,c此时为6;

计算机小白的成长历程——分支与循环(4)for循环_09

这时程序进入了第一个for循环,这时a执行了a++然后再去判断是否小于5,这里涉及一个知识点后置++是先使用再++,所以此时我们看到的a仍然为0;

计算机小白的成长历程——分支与循环(4)#include_10

现在程序运行到了c++这一行,我们也能看到此时a=1,b=5,;

计算机小白的成长历程——分支与循环(4)_for语句_11

现在我们又进入了第二个循环,此时可以看到b仍为5,也就是说,第二个循环会被直接跳过。这里我们可以得出结论:

省略for循环中的变量语句后,变量在进入循环时并不能初始化。

省略判断:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<string.h>

int main()
{
int a = 0, b = 0, c = 0;
for (a = 0;; a++)
{
c++;
for (b = 0;; b++)
{
printf("hehe%d\n", c);
c++;
}
printf("%d\n", c);
}
return 0;
}

下面我们来看看程序会如何执行:

计算机小白的成长历程——分支与循环(4)_for循环_12

此时程序已经走完了6次循环此时a=0,b=5,c=7,打印结果为hehe6;

计算机小白的成长历程——分支与循环(4)_for循环_13

这时程序继续走完了一个循环,我们只能看到打印继续执行hehe,b和c的值也在继续增加,并未有结束循环的条件,也就是说此时语句在第二个循环中进入了死循环,这里我们可以得出结论:

省略for循环中的判断后,循环的判断结果恒为正,循环将进入死循环;

省略递进:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<string.h>

int main()
{
int a = 0, b = 0, c = 0;
for (a = 0; a < 5;)
{
c++;
for (b = 0; b < 5;)
{
printf("hehe%d\n", c);
c++;
}
printf("%d\n", c);
}
return 0;
}

我们来监视一下结果:

计算机小白的成长历程——分支与循环(4)_for循环_14

第一次循环走完,此时a=0,b=0,c=2,打印了hehe1;

计算机小白的成长历程——分支与循环(4)_for循环_15

第二次循环走完,此时a=0,b=0,c=3,打印了hehe2。也就是说在省略递进后,变量因为不会被改变,从而导致判断条件始终满足而导致循环进入死循环,这里我们可以得出结论:

省略for循环中的递进语句后,循环会因变量无法改变,导致判断结果始终不变,从而使循环进入死循环。

(2)变种2——使用多个变量控制循环:

在for循环中我们也可以通过多个变量来控制循环,下面我们通过代码来理解:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<string.h>

int main()
{
int c = 0;
for (int x = 0, y = 0; x < 3 && y < 5; x++, ++)
{
c++;
printf("hehe%d\n", c);
}
return 0;
}

从这个代码中我们就可以看到,此时的for循环中通过变量x和变量y来进行控制,能否正常运行呢?我们来运行一下:

计算机小白的成长历程——分支与循环(4)_#include_16

我们可以看到循环能够正常运行,这里我们可以得到结论:

在for循环中,for循环是可以通过多个变量来控制的。

这里大家只要简单了解一下就可以了,如果随着后续的学习,这一块知识点会继续深入的话,我也会第一时间来跟大家分享的。

最后咱们留下一道题给各位,来帮助各位进一步去理解今天的知识点:

代码语言:javascript
复制
//for循环题目
int main()
{
int i = 0, k = 0;
for (i = 0, k = 0; k = 0; i++, k++)
{
k++;
}
return 0;
}//请问循环要循环几次?

咱们今天的内容到这里就结束了,希望本篇内容能够帮助大家更好的理解for循环的相关知识点,接下来随着学习的深入,我会继续给大家分享我在学习过程中的感受,感谢各位的翻阅,咱们下一篇见。