如果你正在学习循环结构,这篇文章一定要看完,将教会你 C 语言里的所有循环结构,一共有 3 种,分别是 while 循环、do while 循环和 for 循环。

C语言中常用的编程结构有三种(其它编程语言也是如此),它们分别是:

  • 顺序结构:代码从前往后依次执行,没有任何“拐弯抹角”,不跳过任何一条语句,所有的语句都会被执行到。
  • 选择结构:也叫分支结构。代码会被分成多个部分,程序会根据特定条件(某个表达式的运算结果)来判断到底执行哪一部分。
  • 循环结构:程序会重新执行同一段代码,直到条件不再满足,或者遇到强行跳出语句(break 关键字)。

顺序结构不用多说,对选择结构不了解的读者可猛击《C语言if else语句详解icon-default.png?t=O83Ahttps://xiexuewu.github.io/view/446.html》一文系统了解。

所谓循环(Loop),就是重复地执行同一段代码,例如要计算 1+2+3+……+99+100 的值,就要重复进行 99 次加法运算。

C语言while循环

while 循环的一般形式为:

while(表达式){
    语句块
}

意思是,先计算“表达式”的值,当值为真(非 0)时, 执行“语句块”;执行完“语句块”,再次计算表达式的值,如果为真,继续执行“语句块”……这个过程会一直重复,直到表达式的值为假(0),就退出循环,执行 while 后面的代码。

我们通常将“表达式”称为循环条件,把“语句块”称为循环体,整个循环的过程就是不停判断循环条件、并执行循环体代码的过程。

用 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

代码分析:
1) 程序运行到 while 时,因为 i=1,i<=100 成立,所以会执行循环体;执行结束后 i 的值变为 2,sum 的值变为 1。

2) 接下来会继续判断 i<=100 是否成立,因为此时 i=2,i<=100 成立,所以继续执行循环体;执行结束后 i 的值变为 3,sum 的值变为3。

3) 重复执行步骤 2)。

4) 当循环进行到第 100 次,i 的值变为 101,sum 的值变为 5050;因为此时 i<=100 不再成立,所以就退出循环,不再执行循环体,转而执行 while 循环后面的代码。

while 循环的整体思路是这样的:设置一个带有变量的循环条件,也即一个带有变量的表达式;在循环体中额外添加一条语句,让它能够改变循环条件中变量的值。这样,随着循环的不断执行,循环条件中变量的值也会不断变化,终有一个时刻,循环条件不再成立,整个循环就结束了。

如果循环条件中不包含变量,会发生什么情况呢?

1) 循环条件成立时的话,while 循环会一直执行下去,永不结束,成为“死循环”。例如:

#include <stdio.h>
int main(){
    while(1){
        printf("1");
    }
    return 0;
}

运行程序,会不停地输出“1”,直到用户强制关闭。

2) 循环条件不成立的话,while 循环就一次也不会执行。例如:

#include <stdio.h>
int main(){
    while(0){
        printf("1");
    }
    return 0;
}

运行程序,什么也不会输出。

再看一个例子,统计从键盘输入的一行字符的个数:

#include <stdio.h>
int main(){
    int n=0;
    printf("Input a string:");
    while(getchar()!='\n') n++;
    printf("Number of characters: %d\n", n);
    return 0;
}

运行结果:

Input a string:https://xiexuewu.github.io
Number of characters: 26

本例程序中的循环条件为getchar()!='\n',其意义是,只要从键盘输入的字符不是回车就继续循环。循环体n++;完成对输入字符个数计数。

C语言do while循环

除了 while 循环,在 C语言中还有一种 do while 循环。

do while 循环的一般形式为:

do{
    语句块
}while(表达式);

do while 循环与 while 循环的不同在于:它会先执行“语句块”,然后再判断表达式是否为真,如果为真则继续循环;如果为假,则终止循环。因此,do while 循环至少要执行一次“语句块”。

用 do while 计算 1 加到 100 的值:

#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(i<=100);最后的分号 ;,这个必须要有。

while 循环和 do while 各有特点,大家可以适当选择,实际编程中使用 while 循环较多。

C语言for循环

除了 while 循环,C语言中还有 for 循环,它的使用更加灵活,完全可以取代 while 循环。

上节我们使用 while 循环来计算 1 加到 100 的值,代码如下:

#include <stdio.h>
int main(){
    int i, sum=0;
    i = 1;  //语句①
    while(i<=100 /*语句②*/ ){
        sum+=i;
        i++;  //语句③
    }
    printf("%d\n",sum);
    return 0;
}

可以看到,语句 ① ② ③ 被放到了不同的地方,代码结构较为松散。为了让程序更加紧凑,可以使用 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 循环的一般形式为:

for(表达式1; 表达式2; 表达式3){
    语句块
}

它的运行过程为:
1) 先执行“表达式1”。

2) 再执行“表达式2”,如果它的值为真(非 0),则执行循环体,否则结束循环。

3) 执行完循环体后再执行“表达式3”。

4) 重复执行步骤 2) 和 3),直到“表达式2”的值为假,就结束循环。

上面的步骤中,2) 和 3) 是一次循环,会重复执行,for 语句的主要作用就是不断执行步骤 2) 和 3)。

“表达式1”仅在第一次循环时执行,以后都不会再执行,可以认为这是一个初始化语句。“表达式2”一般是一个关系表达式,决定了是否还要继续下次循环,称为“循环条件”。“表达式3”很多情况下是一个带有自增或自减操作的表达式,以使循环条件逐渐变得“不成立”。

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

代码分析:
1) 执行到 for 语句时,先给 i 赋初值1,判断 i<=100 是否成立;因为此时 i=1,i<=100 成立,所以执行循环体。循环体执行结束后(sum 的值为1),再计算 i++。

2) 第二次循环时,i 的值为2,i<=100 成立,继续执行循环体。循环体执行结束后(sum 的值为3),再计算 i++。

3) 重复执行步骤 2),直到第101次循环,此时 i 的值为101,i<=100 不成立,所以结束循环。

由此我们可以总结出 for 循环的一般形式:

for(初始化语句; 循环条件; 自增或自减){
    语句块
}

for循环的三个表达式

for 循环中的“表达式1(初始化条件)”、“表达式2(循环条件)”和“表达式3(自增或自减)”都是可选项,都可以省略(但分号;必须保留)。

1) 修改“从1加到100的和”的代码,省略“表达式1(初始化条件)”:

int i = 1, sum = 0;
for( ; i<=100; i++){
    sum+=i;
}

可以看到,将i=1移到了 for 循环的外面。
 

2) 省略了“表达式2(循环条件)”,如果不做其它处理就会成为死循环。例如:

for(i=1; ; i++) sum=sum+i;

相当于:

i=1;
while(1){
    sum=sum+i;
    i++;
}

所谓死循环,就是循环条件永远成立,循环会一直进行下去,永不结束。死循环对程序的危害很大,一定要避免。
 

3) 省略了“表达式3(自增或自减)”,就不会修改“表达式2(循环条件)”中的变量,这时可在循环体中加入修改变量的语句。例如:

for( i=1; i<=100; ){
    sum=sum+i;
    i++;
} 

4) 省略了“表达式1(初始化语句)”和“表达式3(自增或自减)”。例如:

for( ; i<=100 ; ){
    sum=sum+i;
    i++;
}

相当于:

while(i<=100){
    sum=sum+i;
    i++;
}

5) 3 个表达式可以同时省略。例如:

for( ; ; )  语句

相当于:

while(1)  语句

6) “表达式1”可以是初始化语句,也可以是其他语句。例如:

for( sum=0; i<=100; i++ )  sum=sum+i;

7) “表达式1”和“表达式3”可以是一个简单表达式也可以是逗号表达式。

for( sum=0,i=1; i<=100; i++ )  sum=sum+i;

或:

for( i=0,j=100; i<=100; i++,j-- )  k=i+j;

8) “表达式2”一般是关系表达式或逻辑表达式,但也可是数值或字符,只要其值非零,就执行循环体。例如:

for( i=0; (c=getchar())!='\n'; i+=c );

又如:

for( ; (c=getchar())!='\n' ; )
    printf("%c",c);

C语言循环嵌套

在 C 语言中,if else、while、do while、for 都可以相互嵌套。所谓嵌套(Nest),就是一条语句里面还有另一条语句,例如 for 里面还有 for,while 里面还有 while,或者 for 里面有 while,while 里面有 if else,这都是允许的。

【示例 1】for 嵌套执行的流程。

#include <stdio.h>
int main()
{
    int i, j;
    for(i=1; i<=4; i++){  //外层for循环
        for(j=1; j<=4; j++){  //内层for循环
            printf("i=%d, j=%d\n", i, j);
        }
        printf("\n");
    }
    return 0;
}

运行结果:

i=1, j=1
i=1, j=2
i=1, j=3
i=1, j=4

i=2, j=1
i=2, j=2
i=2, j=3
i=2, j=4

i=3, j=1
i=3, j=2
i=3, j=3
i=3, j=4

i=4, j=1
i=4, j=2
i=4, j=3
i=4, j=4

本例是一个简单的 for 循环嵌套,外层循环和内层循环交叉执行,外层 for 每执行一次,内层 for 就要执行四次。

在 C语言中,代码是顺序、同步执行的,当前代码必须执行完毕后才能执行后面的代码。这就意味着,外层 for 每次循环时,都必须等待内层 for 循环完毕(也就是循环 4 次)才能进行下次循环。虽然 i 是变量,但是对于内层 for 来说,每次循环时它的值都是固定的。

【示例 2】输出一个 4×4 的整数矩阵。

#include <stdio.h>
int main()
{
    int i, j;
    for(i=1; i<=4; i++){  //外层for循环
        for(j=1; j<=4; j++){  //内层for循环
            printf("%-4d", i*j);
        }
        printf("\n");
    }
    return 0;
}

运行结果:

1   2   3   4
2   4   6   8
3   6   9   12
4   8   12  16

外层 for 第一次循环时,i 为 1,内层 for 要输出四次 1*j 的值,也就是第一行数据;内层  for 循环结束后执行 printf("\n"),输出换行符;接着执行外层 for 的 i++ 语句。此时外层 for 的第一次循环才算结束。

外层 for 第二次循环时,i 为 2,内层 for 要输出四次 2*j 的值,也就是第二行的数据;接下来执行 printf("\n") 和 i++,外层 for 的第二次循环才算结束。外层 for 第三次、第四次循环以此类推。

可以看到,内层 for 每循环一次输出一个数据,而外层 for 每循环一次输出一行数据。

【示例 3】输出九九乘法表。

#include <stdio.h>
int main(){
    int i, j;
    for(i=1; i<=9; i++){  //外层for循环
        for(j=1; j<=i; j++){  //内层for循环
            printf("%d*%d=%-2d  ", i, j, i*j);
        }
        printf("\n");
    }

    return 0;
}

运行结果:

1*1=1
2*1=2   2*2=4
3*1=3   3*2=6   3*3=9
4*1=4   4*2=8   4*3=12  4*4=16
5*1=5   5*2=10  5*3=15  5*4=20  5*5=25
6*1=6   6*2=12  6*3=18  6*4=24  6*5=30  6*6=36
7*1=7   7*2=14  7*3=21  7*4=28  7*5=35  7*6=42  7*7=49
8*1=8   8*2=16  8*3=24  8*4=32  8*5=40  8*6=48  8*7=56  8*8=64
9*1=9   9*2=18  9*3=27  9*4=36  9*5=45  9*6=54  9*7=63  9*8=72  9*9=81

和示例 2 一样,内层 for 每循环一次输出一条数据,外层 for 每循环一次输出一行数据。

需要注意的是,内层 for 的结束条件是j<=i。外层 for 每循环一次,i 的值就会变化,所以每次开始内层 for 循环时,结束条件是不一样的。具体如下:

  • 当 i=1 时,内层 for 的结束条件为 j<=1,只能循环一次,输出第一行。
  • 当 i=2 时,内层 for 的结束条件是 j<=2,循环两次,输出第二行。
  • 当 i=3 时,内层 for 的结束条件是 j<=3,循环三次,输出第三行。
  • 当 i=4、5、6... 时,以此类推。

九九乘法表还有更多输出方式,请查看:C语言输出九九乘法表(5种解法)icon-default.png?t=O83Ahttps://xiexuewu.github.io/view/455.html

总结

C语言中常用的循环结构有 while 循环和 for 循环,它们都可以用来处理同一个问题,一般可以互相代替。

除了 while 和 for,C语言中还有一个 goto 语句,它也能构成循环结构。不过由于 goto 语句很容易造成代码混乱,维护和阅读困难,饱受诟病,不被推荐,而且 goto 循环完全可以被其他循环取代,所以后来的很多编程语言都取消了 goto 语句,我们也不再讲解。

国内很多大学仍然讲解 goto 语句,但也仅仅是完成教材所设定的课程,goto 语句在实际开发中很难见到。

对于 while 和 do while 循环,循环体中应包括使循环趋于结束的语句。

对于 while 和 do while 循环,循环变量的初始化操作应该在 while 和 do while 语句之前完成,而 for 循环可以在内部实现循环变量的初始化。

for 循环是最常用的循环,它的功能强大,一般都可以代替其他循环。

掌握了循环结构,紧接着就是学习 C语言中的 continue 和 break 的用法,感兴趣的读者可猛击《C语言break和continue用法详解》一文系统学习。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐