前言
循环结构是C语言三大基本结构之一,是结构化程序设计中最重要的结构。循环结构程序主要使用循环语句实现(循环语句是专门用于循环程序执行流程的语句)。在C语言中,主要有for循环语句,while语句,do-while语句,和goto语句(由于过多的goto语句会破坏程序完整的逻辑性,这里我们不做重点介绍)。
循环结构即在给定条件成立的条件下,反复执行某语句段,直到条件不成立为止,我们将给定的条件成为循环条件,反复执行的语句称为循环体。
根据循环条件和循环体执行次序,可以分为当型循环、直到型循环。在WHILE(当型)语句中,是当条件满足时执行循环体;而在UNTIL(直到型)语句中,是当条件不满足时执行循环体。
- 当型循环
当计算机遇到WHILE语句时,先判断条件的真假,如果条件符合,就执行WHILE与WEND之间的循环体;然后再检查上述条件,如果条件仍符合,再次执行循环体,这个过程反复进行,直到某一次条件不符合为止。
这时,计算机将不执行循环体,直接跳到WEND语句后,接着执行WEND之后的语句。因此,当型循环有时也称为“前测试型”循环。
- 直到型循环
直到型循环又称为“后测试型”循环,从UNTIL型循环结构分析,计算机执行该语句时,先执行一次循环体,然后进行条件的判断,如果条件不满足,继续返回执行循环体,然后再进行条件的判断。
这个过程反复进行,直到某一次条件满足时,不再执行循环体,跳到LOOP UNTIL语句后执行其他语句,是先执行循环体后进行条件判断的循环语句。
For循环语句
for语句属于直到型循环,使用非常广泛。
For语句定义
for语句由初始表达式,循环控制表达式,循环置位表达式和循环体构成。其一般形式为:
for(表达式1;表达式2;表达式3)
{
语句段
}
//注释
表达式1称为初始表达式,作为for语句初始条件,常常用来给循环变量赋初值,一般为赋值表达式
表达式2称为循环控制表达式,通常作为循环条件,一般为逻辑表达式
表达式3称为循环置位表达式,即迭代表达式,用来修改循环变量的值
上述表达式既可以是单个语句,也可以是由多个表达式构成的逗号表达式
为了更好地理解定义,我们给出一个具有趣味性的例子:
for(time=now;time<=forever;time++)
{
love++;
happiness++;
}
//注释
结合程序猿的三行情诗,我们可以更好地理解for语句。
time=now即为表达式1,为初始表达式,意思是从现在开始
time<=forever即为表达式2,为循环控制表达式,意思是直到永远
time++即为表达式3,为循环置位表达式,意思是随着时间流逝
love++;happiness++;为语句段,意思是每天多爱你一点点,每天幸福一点点
所有结合起来的意思,不用我多说了吧。
需要注意的有,三个表达式仅仅作为执行某项功能存在,如果存在其他语句代替某一个表达式的功能,则在括号中该语句可以省略。(也就意味着不是每一个循环语句都具有完整的三个表达式),但分号不能省略。
关键字for与括号之间没有空格,也可以加上一个空格来使代码美观整齐。
for语句的执行过程
for语句按照从左到右,从上到下,自两边到中间的执行顺序执行,具体执行步骤为:
-
先执行“表达式1”。
-
再执行“表达式2”,如果它的值为真(非0),则执行循环体,否则结束循环。
-
执行完循环体后再执行“表达式3”。
-
重复执行步骤 2) 和 3),直到“表达式2”的值为假,就结束循环。
上面的步骤中,2) 和 3) 是一次循环,会重复执行,for 语句的主要作用就是不断执行步骤 2) 和 3)。
在整个for循环执行过程中,表达式2是for循环的控制表达式,对循环语句执行起主要的控制作用。
画出执行流程图,如下所示:
在源代码中执行顺序为:
for语句应用实例
//从1一直加到100
#include <stdio.h>
int main(){
int i, sum=0;
for(i=1; i<=100; i++){
sum+=i;
}
printf("%d\n",sum);
return 0;
}
运行结果:
5050
执行流程为:
-
执行到 for 语句时,先给 i 赋初值1,判断 i<=100 是否成立;因为此时 i=1,i<=100 成立,所以执行循环体。循环体执行结束后(sum的值为1),再计算 i++。
-
第二次循环时,i 的值为2,i<=100 成立,继续执行循环体。循环体执行结束后(sum的值为3),再计算 i++。
-
重复执行步骤 2),直到第101次循环,此时 i 的值为101,i<=100 不成立,所以结束循环。
for语句的三个表达式具体分析
for循环中的“表达式1(初始化条件)”、“表达式2(循环条件)”和“表达式3(自增或自减)”都是可选项,都可以省略(但分号;必须保留)
我们以上面的程序为例,进行分析:
- 省略表达式1(初始化条件)
int i = 1;
for( ; i<=100; i++)
{
sum+=i;
}
- 省略表达式2(循环控制表达式)
for(i=1; ; i++)
sum=sum+i;
如果不做其它处理就会成为死循环(循环条件永远成立,循环会一直进行下去,永不结束)
- 省略表达式3(循环置位表达式)
for( i=1; i<=100; )
{
sum=sum+i;
i++;
}
省略了“表达式3(自增或自减)”,就不会修改“表达式2(循环条件)”中的变量,这时可在循环体中加入修改变量的语句
- 补充两个经常使用的特殊for语句
无限循环语句
for( ; ; )
{
语句段;
}
重复读取语句
for( ; (c=getchar())!=‘\n‘ ; )
printf("%c",c);
for语句的嵌套使用
嵌套规则很简单,我们给出一般形式,然后用实例进行学习
- for语句嵌套定义
一般形式为:
for(表达式01;表达式02;表达式03)
for(表达式11,;表达式12,;表达式13)
…………
for(表达式n1;表达式n2;表达式n3)
{
语句段;
}
//一般情况下n<=3;
- 实例分析:打印九九乘法表
这里我们需要用双重循环完成打印九九乘法表的任务,这里我们给出代码和分析:
#include<stdio.h>
int main()
{
int i=0,j=0;
int mult=0;
for(i=1;i<=9;i++)//打印控制行
{
for(j=1;j<=i;j++)
{
printf("%d*%d=%-3d",j,i,i*j);
}
printf("\n");
}
return 0;
}
执行结果:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
分析:
程序将i作为内层循环的控制变量,控制列输出总是小于等于行输出数,程序输出结果为i*j=k格式的等式,实现了九九乘法表的效果,使用%3d格式输出乘积,实现对齐效果。
While语句与do-while语句
while语句和for语句一样属于直到型语句,do-while语句属于当型语句。
while语句定义及应用
while循环的一般形式为:
while(表达式){
语句块
}
即先计算“表达式”的值,当值为真(非0)时, 执行“语句块”;执行完“语句块”,再次计算表达式的值,如果为真,继续执行“语句块”……这个过程会一直重复,直到表达式的值为假(0),就退出循环,执行 while 后面的代码。
通常将“表达式”称为循环条件,把“语句块”称为循环体,整个循环的过程就是不停判断循环条件、并执行循环体代码的过程。
实例:
//计算1加到100的值
#include <stdio.h>
int main(){
int i=1, sum=0;
while(i<=100)
{
sum+=i;
i++;
}
printf("%d\n",sum);
return 0;
}
运行结果:
5050
执行过程:
-
程序运行到 while 时,因为 i=1,i<=100 成立,所以会执行循环体;执行结束后 i 的值变为 2,sum 的值变为 1。
-
接下来会继续判断 i<=100是否成立,因为此时 i=2,i<=100 成立,所以继续执行循环体;执行结束后 i 的值变为 3,sum 的值变为3。
-
重复执行步骤 2)。
-
当循环进行到第100次,i 的值变为 101,sum 的值变为5050;因为此时 i<=100 不再成立,所以就退出循环,不再执行循环体,转而执行while循环后面的代码。
由此,我们可以得到while 循环的思路:
- 设置一个带有变量的循环条件,也即一个带有变量的表达式;
- 在循环体中额外添加一条语句,让它能够改变循环条件中变量的值。
- 随着循环的不断执行,循环条件中变量的值也会不断变化,当循环条件不再成立,循环结束
当循环条件中没有变量时,可以分为两种情况:
- while(1)
#include <stdio.h>
int main()
{
while(1)
{
printf("666");
}
return 0;
}
运行结果:
66666666…………
while 循环会一直执行下去,永不结束,成为“死循环”
- while(0)
#include <stdio.h>
int main()
{
while(0)
{
printf("6");
}
return 0;
}
运行结果:
运行结果为空,神木都不输出.
while语句嵌套使用
- 嵌套规则如下:
while(表达式1)
while(表达式2)
while(表达式3)
…………
while(表达式n)
{
语句段;
}
- 实例:打印五行数字1-5
#include<stdio.h>
int main()
{
int i=1,j=1;
while(i<=5)
{
while(j<=5)
{
printf("%d ",j);
j++;
}
printf("\n");
i++;
}
return 0;
}
执行结果:
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
do-while语句的定义及应用
do-while语句和while语句执行规则相同,但do-while语句会首先执行循环体一次,然后判断表达式,这也是和直到型语句的差别。
do-while循环的一般形式为:
do{
语句块
}while(表达式);
//补充
do-while循环与while循环的不同在于:它会先执行“语句块”,然后再判断表达式是否为真,
如果为真则继续循环;如果为假,则终止循环。因此,do-while 循环至少要执行一次“语句块”。
执行规则:
do-while语句首先执行循环体,然后判断表达式是否为真(非0),若表达式为真,则继续返回执行循环体,否则退出循环。
尤其需要注意的是:while(表达式);最后的分号;不能省略。
实例:
#include <stdio.h>
int main()
{
int i=1, sum=0;
do
{
sum+=i;
i++;
}while(i<=100);
printf("%d\n", sum);
return 0;
}
执行结果:
5050
和while语句类似的,我们对do-while中while中的表达式进行限制,分为两种情况:
- do-while(1)
#include <stdio.h>
int main()
{
do
{
printf("6");
}while(1);
return 0;
}
运行结果:
66666666…………
do-while 循环会一直执行下去,永不结束,成为“死循环”
- do-while(0)
#include <stdio.h>
int main()
{
do
{
printf("6");
}while(0);
return 0;
}
运行结果:
6
从这里我们可以更明显的感受到while语句,与do-while语句存在的差异。
do-while循环嵌套:
- 一般格式为:
do
{
do
{
do
{
循环体3;
…………
}while(表达式3)
循环体2;
} while (表达式2);
循环体1;
} while (表达式1);
- 实例:打印数字三角形
#include <stdio.h>
int main()
{
int i=1,j;
do
{
j=1;
do
{
printf("%d ",j);
j++;
}while( j<=i );
printf("\n");
i++;
}while( i<=5 );
return 0;
}
执行结果:
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
for语句与while语句的相互转化
一般情况下,我们看到while与for具有类似的性质,都可以实现相同的循环功能,那while与for是不是可以相互转化呢?答案是显然的。
转换规则如下:
初始化
while(条件表达式)
{
循环体
标志变量修改
}
-------等价转换线---------
for(初始化;条件;标志变量修改)
{
循环体
}
我们举一个栗子就可以理解这个转换过程,我们不做过多解释。
实现1-100的加法
- while型
#include <stdio.h>
int main()
{
int i, sum=0;
i = 1; //语句①
while(i<=100 /*语句②*/ )
{
sum+=i;
i++; //语句③
}
printf("%d\n",sum);
return 0;
}
语句①②③被放到了不同的地方,代码结构较为松散,转换为for后:
- for型
#include <stdio.h>
int main()
{
int i, sum=0;
for(i=1/*语句①*/; i<=100/*语句②*/; i++/*语句③*/)
{
sum+=i;
}
printf("%d\n",sum);
return 0;
}
for 循环中,语句①②③被集中到了一起,代码结构更加清晰;
几种循环的比较:
- for和while以及do while这3种循环都可以用来处理同一问题,一般情况下它们可以互相代替。
- while和do-while循环,是在while后面指定循环条件的,在循环体中应包含使循环趋于结束的语句(如i++,或i=i+1等)。
for循环可以在表达式3中包含使循环趋于结束的操作,甚至可以将循环体中的操作全部放到表达式3中。因此for语句的功能更强,凡用while循环能完成的,用for循环都能实现。
- 用while和do-while循环时,循环变量初始化的操作应在while和do-while语句之前完成。而for语句可以在表达式1中实现循环变量的初始化。
循环控制语句:break,continue
使用方法:
break;
continue;
后面没有任何参数,且都有分号,不可省略.
break 语句,它不仅可以跳出“循环体”,还可以跳出 switch,break 也只能用于这两种情况。
需要注意的有:
break 语句不能用于循环语句和 switch 语句之外的任何其他语句中。
循环的三种形式都可以用 break 跳出来,但 break 只能跳出一层循环。
当有多层循环嵌套的时候,break只能跳出“包裹”它的最里面的那一层循环,无法一次跳出所有循环。
在多层 switch 嵌套的程序中,break 也只能跳出其所在的距离它最近的 switch。但多层 switch 嵌套实在是少见。
而continue 的用法十分简单,其作用为结束本次循环,即跳过循环体中下面尚未执行的语句,然后进行下一次是否执行循环的判定。
区别
continue 语句和 break 语句的区别为:
- continue 语句只结束本次循环,而不是终止整个循环。
- break 语句则是结束整个循环过程,不再判断执行循环的条件是否成立。
此外,continue 只能在循环语句中使用,即只能在 for、while 和 do…while 中使用,除此之外 continue 不能在任何语句中使用。
所以,continue 不能在 switch 中使用,除非 switch 在循环体中。
此时 continue 表示的也是结束循环体的本次循环,跟 switch 也没有关系。
参考文献:
①《C语言从入门到精通》
②for,while,do-while循环流程图的的画法总结