C语言入门系列之5.循环控制结构程序

CuterCorley
• 阅读 1580

@toc

一、概述

循环结构是程序中一种很重要的结构。 其特点是:在给定条件成立时,反复执行某程序段,直到条件不成立为止。 给定的条件称为循环条件,反复执行的程序段称为循环体。 C语言提供了多种循环语句,可以组成各种不同形式的循环结构:

  • goto语句和if语句构成循环;
  • while语句;
  • do-while语句;
  • for语句。

二、goto语句和用goto语句构成循环

goto语句是一种无条件转移语句,与BASIC中的goto语句相似。 goto语句的使用格式为:

goto  语句标号;

其中标号是一个有效的标识符,这个标识符加上一个冒号:一起出现在函数内某处, 执行goto语句后,程序将跳转到该标号处并执行其后的语句。 标号必须与goto语句同处于一个函数中,但可以不在一个循环层中。 通常goto语句与if条件语句连用, 当满足某一条件时,程序跳到标号处运行。 要注意,通常不用goto语句,主要因为它将使程序层次不清,且不易读,但在多层嵌套退出时, 用goto语句则比较合理。

练习: 用goto语句和if语句构成循环求1-100所有数之和。 代码如下:

#include <stdio.h>

int main(){
    int i = 1, sum = 0;
    loop: if(i <= 100){
        sum += i;
        i++;
        goto loop;
    }
    printf("Sum=%d", sum);

    return 0;
}

打印:

Sum=5050

显然,此时求出了1-100的和。

三、while语句

1.基本使用

while语句的一般形式为:

while(表达式)语句

其中表达式是循环条件,语句为循环体。 while语句的语义是: 计算表达式的值,当值为真(非0)时, 执行循环体语句。 其执行过程如下: C语言入门系列之5.循环控制结构程序 显然可以得到,如果表达式的值一开始就为0,则语句一次也不会被执行。

练习: 用while语句求和1-100。 代码如下:

#include <stdio.h>

int main(){
    int i = 1, sum = 0;
    while(i <= 100){
        sum += i;
        i++;
    }
    printf("Sum=%d", sum);

    return 0;
}

打印:

Sum=5050

显然,结果与之前的相同。

可能会出现死循环,示例如下:

#include <stdio.h>

int main(){
    int i = 1, sum = 0;
    while(i <= 100)
        sum += i;
        i++;
    printf("Sum=%d", sum);

    return 0;
}

只是在前面的基础上去掉了大括号,再运行会发现程序堵塞,一直不输出结果,查看CPU占用情况会发现编译器占用了大量的CPU,此时产生了死循环,因为去掉大括号后,while循环默认只包括赶紧跟在其后的第一条语句,即sum += i;,而不再执行i自增,所以i一直为1,while循环的条件i <= 100的条件恒成立,所以循环一直进行下去,永不结束,此时只能强制关闭程序才能终止运行。

再做一个练习: 统计从键盘输入一行字符的个数。 代码如下:

#include <stdio.h>

int main(){
    int n = 0;
    printf("Input a string:\n");
    while(getchar() != '\n'){
        n++;
    }
    printf("count=%d", n);

    return 0;
}

打印:

Input a string:
123abc@#$,.?
count=12

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

2.注意事项

(1)while语句中的表达式一般是关系表达式或逻辑表达式,只要表达式的值为真(非0)即可继续循环。 练习如下:

#include <stdio.h>

int main(){
    int a = 0, n;
    printf("Input a number:\n");
    scanf("%d", &n);
    while(n--){
        printf("%d ", a++*2);
    }

    return 0;
}

打印:

Input a number:
10
0 2 4 6 8 10 12 14 16 18

此时,只要n不等于0,循环会一直进行。

(2)循环体如包括有一个以上的语句,则必须用{}括起来,组成复合语句,建议只有一条语句时也用大括号括起来。

四、do-while语句

do-while语句的一般形式为:

do
    语句
while (表达式);

其执行过程如下: C语言入门系列之5.循环控制结构程序

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

用do-while循环求和测试如下:

#include <stdio.h>

int main(){
    int i = 1, sum = 0;
    do{
        sum += i;
        i++;
    }
    while(i <= 100);
    printf("Sum=%d", sum);

    return 0;
}

运行结果与之前相同。

如果最开始的条件就为假,则while循环一次都不会执行,do-while循环会执行一次,这是while循环和do-while循环的区别之一。

五、for语句

1.基本使用

在C语言中,for语句使用最为灵活,它完全可以取代while语句。 它的一般形式为:

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

其执行过程如下:

  • (1)先求解表达式1。
  • (2)求解表达式2,若其值为真(非0),则执行for语句中指定的内嵌语句,然后执行下面第(3)步;若其值为假(为0),则结束循环,转到第(5)步。
  • (3)求解表达式3。
  • (4)转回上面第(2)步继续执行。
  • (5)循环结束,执行for语句下面的一个语句。

for语句最简单也是最容易理解的形式如下:

for(循环变量赋初值; 循环条件; 循环变量增量) 语句

循环变量赋初值总是一个赋值语句,它用来给循环控制变量赋初值; 循环条件是一个关系表达式,它决定什么时候退出循环; 循环变量增量,定义循环控制变量每循环一次后按什么方式变化。 这三个部分之间用;分开。

求和用for循环改变如下:

#include <stdio.h>

int main(){
    int i, sum = 0;
    for(i = 1; i <= 100; i++){
        sum += i;
    }
    printf("Sum=%d", sum);

    return 0;
}

运算结果与前面相同。 先给i赋初值1,判断i是否小于等于100,若是则执行语句,之后值增加1,再重新判断, 直到条件为假,即i>100时,结束循环。

2.注意事项

(1)for循环中的表达式1(循环变量赋初值)表达式2(循环条件)表达式3(循环变量增量) 都是选择项, 即可以缺省,但;不能缺省。

(2)省略了表达式1(循环变量赋初值),表示不对循环控制变量赋初值。

上面代码也可以写成:

#include <stdio.h>

int main(){
    int i = 1, sum = 0;
    for( ; i <= 100; i++){
        sum += i;
    }
    printf("Sum=%d", sum);

    return 0;
}

效果一样。

(3)省略了表达式2(循环条件),则不做其他处理时便成为死循环。 例如

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

即是一个死循环。

(4)省略了表达式3(循环变量增量), 则不对循环控制变量进行操作,这时可在语句体中加入修改循环控制变量的语句。

代码还可以写成:

#include <stdio.h>

int main(){
    int i, sum = 0;
    for(i = 1; i <= 100; ){
        sum += i;
        i++;
    }
    printf("Sum=%d", sum);

    return 0;
}

(5)还可以省略表达式1(循环变量赋初值)表达式3(循环变量增量)

代码还可以改成:

#include <stdio.h>

int main(){
    int i = 1, sum = 0;
    for( ; i <= 100; ){
        sum += i;
        i++;
    }
    printf("Sum=%d", sum);

    return 0;
}

(6)3个表达式都可以省略。 例如for( ; ; )语句相当于while(1)语句。

(7)表达式1可以是设置循环变量的初值的赋值表达式,也可以是其他表达式。

代码还可以写为:

#include <stdio.h>

int main(){
    int i = 1,sum;
    for(sum = 0; i <= 100; ){
        sum += i;
        i++;
    }
    printf("Sum=%d", sum);

    return 0;
}

(8)表达式1和表达式3可以是一个简单表达式也可以是逗号表达式。 例如:

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

求和代码还可以写为:

#include <stdio.h>

int main(){
    int i, sum;
    for(i = 1, sum = 0 ; i <= 100; ){
        sum += i;
        i++;
    }
    printf("Sum=%d", sum);

    return 0;
}

(9)表达式2一般是关系表达式或逻辑表达式,但也可是数值表达式或字符表达式,只要其值非零,就执行循环体。 例如for(i=0; (c=getchar())!='\n'; i+=c);

3.循环的嵌套

循环的嵌套是指循环中的语句又是一个循环。

练习如下:

#include <stdio.h>

int main(){
    int i, j, k;
    for(i = 1; i <= 3; i++){
        for(j = 1; j <= 4; j++){
            for(k = 1; k <= 5; k++){
                printf("%d, %d, %d\n", i, j, k);
            }
        }
    }

    return 0;
}

打印:

1, 1, 1
1, 1, 2
1, 1, 3
1, 1, 4
1, 1, 5
1, 2, 1
1, 2, 2
1, 2, 3
1, 2, 4
1, 2, 5
1, 3, 1
1, 3, 2
1, 3, 3
1, 3, 4
1, 3, 5
1, 4, 1
1, 4, 2
1, 4, 3
1, 4, 4
1, 4, 5
2, 1, 1
2, 1, 2
2, 1, 3
2, 1, 4
2, 1, 5
2, 2, 1
2, 2, 2
2, 2, 3
2, 2, 4
2, 2, 5
2, 3, 1
2, 3, 2
2, 3, 3
2, 3, 4
2, 3, 5
2, 4, 1
2, 4, 2
2, 4, 3
2, 4, 4
2, 4, 5
3, 1, 1
3, 1, 2
3, 1, 3
3, 1, 4
3, 1, 5
3, 2, 1
3, 2, 2
3, 2, 3
3, 2, 4
3, 2, 5
3, 3, 1
3, 3, 2
3, 3, 3
3, 3, 4
3, 3, 5
3, 4, 1
3, 4, 2
3, 4, 3
3, 4, 4
3, 4, 5

练习: 输出以下图形: C语言入门系列之5.循环控制结构程序

代码如下:

#include <stdio.h>

int main(){
    int i, j;
    for(i = 1; i <= 6; i++){
        for(j = 1; j <= i; j++){
            putchar('*');
        }
        printf("\n");
    }

    return 0;
}

打印:

*
**
***
****
*****
******

显然,得到了想要的结果。

六、几种循环方式的比较

  1. 四种循环都可以用来处理同一问题,一般情况下它们可以互相代替。 一般不提倡用goto型循环。

  2. 在while循环和do-while循环中,只在while后面的括号内指定循环条件,因此为了使循环能正常结束,应在循环体中加入使循环趋于结束的语句(如i++,或i=i+1等)。 for循环可以在表达式3中包含使循环趋于结束的操作,甚至可以将循环体中的操作全部放到表达式3中。 因此for语句的功能更强,凡是用while循环能完成的,用for循环都能实现。

  3. 用while和do-while循环时,循环变量初始化的操作应在while和do-while语句之前完成,而for语句可以在表达式1中实现循环变量的初始化。

  4. while循环、do-while循环和for循环,可以用break语句跳出循环,用continue语句结束本次循环,而对用goto语句和if语句构成的循环,不能用break语句和continue语句进行控制。

练习: 有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 实现原理: 可填在百位、十位、个位的数字都是1、2、3、4,组成所有的排列后再去掉不满足条件的排列。

代码如下:

#include <stdio.h>

int main(){
    int i, j, k;
    for(i = 1; i <= 4; i++){
        for(j = 1; j <= 4; j++){
            for(k = 1; k <= 4; k++){
                if(i != j && i != k && j != k){     // 确保i、j、k三位互不相同
                    printf("%d%d%d\n", i, j, k);
                }
            }
        }
    }

    return 0;
}

打印:

123
124
132
134
142
143
213
214
231
234
241
243
312
314
321
324
341
342
412
413
421
423
431
432

七、break和continue语句

1.break语句

break语句用来从循环体内跳出循环体,即提前结束循环,接着执行循环下面的语句。 一般形式:

break;

break语句不能用于循环语句和switch语句之外的任何其他语句中。 注意:

  • break语句对if-else的条件语句不起作用。
  • 在多层循环中,一个break语句只向外跳一层。

练习如下:

#include <stdio.h>

int main(){
    double pi = 3.14159, area;
    int r;
    for(r = 1; r <= 10; r++){
        area = pi * r * r;
        if(area > 100){
            break;
        }
        printf("r=%d, area=%g\n", r, area);
    }

    return 0;
}

打印:

r=1, area=3.14159
r=2, area=12.5664
r=3, area=28.2743
r=4, area=50.2654
r=5, area=78.5397

显然,虽然理论上可以循环10次,但是由于r=6时面积已经大于100,所以执行break语句,提前结束循环,即不再继续执行其余的几次循环。

再来一个稍复杂的练习:

#include <stdio.h>
#include <conio.h>

int main(){
    int i = 0;
    char c;
    while(1){
        c = '\0';
        while(c!=13 && c!=27){      // 键盘接收字符直到按回车或Esc键
            c = getch();
            printf("%c\n", c);
        }
        if(c==27){      // 判断,若按Esc键则退出循环
            break;
        }
        i++;
        printf("The number is %d\n", i);
    }
    printf("End");

    return 0;
}

打印:

a
s
d
f
g

The number is 1
q
w
e
r
t

The number is 2
1
2
3
4
5

The number is 3

End

显然,内层循环按回车或Esc退出,外层循环按Esc退出;+ -+ + + + + + + + + + + + +

其中getch()适用于从控制台读取一个字符、但不显示在屏幕上,需要引入头文件conio.h

2.continue语句

作用为结束本次循环,即跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定。 一般形式:

continue;

练习如下:

#include <stdio.h>

int main(){
    double pi = 3.14159, area;
    int r;
    for(r = 1; r <= 10; r++){
        area = pi * r * r;
        if(area > 100 && area < 120){
            continue;
        }
        printf("r=%d, area=%g\n", r, area);
    }

    return 0;
}

打印:

r=1, area=3.14159
r=2, area=12.5664
r=3, area=28.2743
r=4, area=50.2654
r=5, area=78.5397
r=7, area=153.938
r=8, area=201.062
r=9, area=254.469
r=10, area=314.159

显然,此时只是跳过了第6次循环,后面的迭代继续进行。

3.continue和break的对比

continue语句只结束本次循环,而不是终止整个循环的执行; break语句则是结束整个循环过程,不再判断执行循环的条件是否成立。

练习: 显示输入的字符,如果按的是Esc键,则退出循环;如果按的是Enter键,则不做任何处理,继续输入下一个字符。 代码如下:

#include <conio.h>

int main(){
    char c;
    for( ; ; ){
        c = getch();        // 字符输入函数
        if(c==27){
            break;
        }
        if(c==13){
            continue;
        }
        putch(c);       // 显示输入的字符
    }
    getch();    // 让程序停一下,按任意键继续

    return 0;
}

打印:

abcdef123

此时输入普通字符会显示,输入回车会跳过、不换行,输入Esc会跳出循环,再输入即退出。 其中,getch()putch()需要引入conio.h头文件。

练习: 把100~200之间的不能被3整除的数输出。 实现原理: 当n能被3整除时,执行continue语句,结束本次循环(即跳过printf函数语句),只有n不能被3整除时才执行printf函数。 代码如下:

#include <stdio.h>

int main(){
    int i;
    for(i = 100; i <= 200; i++){
        if(i % 3 == 0){
            continue;
        }
        printf("%d\n", i);
    }

    return 0;
}

打印:

100
101
103
104
106
107
109
110
112
113
115
116
118
119
121
122
124
125
127
128
130
131
133
134
136
137
139
140
142
143
145
146
148
149
151
152
154
155
157
158
160
161
163
164
166
167
169
170
172
173
175
176
178
179
181
182
184
185
187
188
190
191
193
194
196
197
199
200

练习: 用π/4 ≈ 1-1/3+1/5-1/7+…公式求π的近似值,直到某一项的绝对值小于为止。 实现原理: 要确定计算的精度,可以配合while循环语句用fabs()函数确定精度来退出; 据观察,分子不变,分母却每次递增2,且正负切换; 结果乘以4。

代码如下:

#include <stdio.h>
#include <math.h>

int main(){
    int i = 1;
    double s = 1.0;
    double pt = 0, pi;
    while(fabs(s/i) > 1e-8){
        pt += s / i;
        s = -s;
        i += 2;
    }
    pi = pt * 4;
    printf("PI=%10.8f", pi);

    return 0;
}

打印:

PI=3.14159263

显然,得到了π的估计值。

练习: 求Fibonacci数列前40个数。 这个数列有如下特点:第1,2两个数为1,1;从第3个数开始,该数是其前面两个数之和。 即

F(1) = 1 (n=1) F(2) = 1 (n=2) F(n) = F(n-1)+F(n-2) (n≥3)

代码如下:

#include <stdio.h>

int main(){
    long i, f1 = 1, f2 = 1;
    for(i = 1; i <= 20; i++){
        printf("%10ld %10ld ", f1, f2);
        f1 += f2;
        f2 += f1;
        if(i % 2 == 0){
            printf("\n");
        }
    }    

    return 0;
}

打印:

         1          1          2          3
         5          8         13         21
        34         55         89        144
       233        377        610        987
      1597       2584       4181       6765
     10946      17711      28657      46368
     75025     121393     196418     317811
    514229     832040    1346269    2178309
   3524578    5702887    9227465   14930352
  24157817   39088169   63245986  102334155

练习: 写一个程序,允许输入一个数,并判断这个数是否为素数。 其中,素数又称质数,指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。 换句话说,只有两个正因数(1和自己)的自然数即为素数。

代码如下:

#include <stdio.h>
#include <math.h>

int main(){
    int n, i, prime = 1;
    printf("Input a number:\n");
    scanf("%d", &n);
    for(i = 2; i <= sqrt(n); i++){
        if(n % i == 0){
            prime = 0;
            break;
        }
    }
    if(prime){
        printf("%d is a prime number\n", n);
    }
    else{
        printf("%d is not a prime number\n", n);
    }

    return 0;
}

打印:

Input a number:
23
23 is a prime number

其中,sqrt()函数用来求一个数的算术平方根,返回double型的值。

练习: 求100~200间的全部素数并打印出来。 代码如下:

#include <stdio.h>
#include <math.h>

int main(){
    int n, i, c = 1;
    for(n = 100; n <= 200; n++){
        int prime = 1;
        for(i = 2; i <= sqrt(n); i++){
            if(n % i == 0){
                prime = 0;
                break;
            }
        }
        if(prime){
            printf("% 4d", n);
            if(c % 5 == 0){
                printf("\n");
            }
            c++;
        }
    }

    return 0;
}

打印:

 101 103 107 109 113
 127 131 137 139 149
 151 157 163 167 173
 179 181 191 193 197
 199

练习: 为使电文保密,往往按一定规律将其转换成密码,收报人再按约定的规律将其译回原文。 例如,可以按以下规律将电文变成密码:

将字母A变成字母E,a变成e,即变成其后的第4个字母,W变成A,X变成B,Y变成C,Z变成D。 如输入China!得到Glmre!

代码如下:

#include <stdio.h>

int main(){
    char c = getchar();
    while(c != '\n'){
        if(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'){
            if(c >= 'w' && c <= 'z' || c >= 'W' && c <= 'Z'){
                c = c - 22;
            }
            else{
                c = c + 4;
            }
        }
        putchar(c);
        c = getchar();
    }
    printf("\n");

    return 0;
}

打印:

zxcvb12345ASDFGqweRT
dbgzf12345EWHJKuaiVX

本文原文首发来自博客专栏C语言学习,由本人转发至https://www.helloworld.net/p/75QH9YtZwfjG,其他平台均属侵权,可点击https://blog.csdn.net/CUFEECR/article/details/105724161查看原文,也可点击https://blog.csdn.net/CUFEECR浏览更多优质原创内容。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
CuterCorley CuterCorley
3年前
C语言入门系列之3.顺序程序设计和输入输出
从程序流程的角度来看,程序可以分为三种基本结构,即顺序结构、分支结构、循环结构,这三种基本结构可以组成各种复杂程序,C语言提供了多种语句来实现这些程序结构。同时C语言提供的输入输出的函数为IO提供了方便的工具。一、C语句介绍1.C基本语句C程序的执行部分是由语句组成的,程序的功能也是由执行语句实现的。C语句可分为以下五类:表达式语句表达式语句:
Stella981 Stella981
2年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
Java05
Java05Java基础语法(四)循环结构循环结构(重复/迭代):根据条件重复执行部分语句1、while循环结构while(条件表达式){     循环体语句;}1)语法:a、while是关键字        b、“条件表达式”必须用括号括起来        c、“{}”表示循环的控制范围,若没有“{}”,whil
Stella981 Stella981
2年前
Shell编程之while&until循环详解
循环语句命令常用于执行一条指令或者一组指令,那么直到条件不在满足时停止,在shell脚本中循环语句常见有whileuntilforselect循环语句。在while循环语句主要用来重复执行一组命令或语句,在企业实际应用中,常用于守护进程持续运行的程序。1、在这么多语句中,while循环有它的语法格式,如下:
小万哥 小万哥
3个月前
深入解析 C 语言中的 for 循环、break 和 continue
C语言中的for循环当您确切地知道要循环执行代码块的次数时,可以使用for循环而不是while循环cfor(语句1;语句2;语句3)//要执行的代码块语句1在执行代码块之前执行(一次)。语句2定义执行代码块的条件。语句3在执行代码块后执行(每次)。下面的示
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这