C语言:分支与循环

目录

一、分支语句其一 if else

1.if 语句

2.else 语句 

3.else if 语句

4.悬空else问题

二、关系操作符

三、条件操作符

四、逻辑操作符

1.逻辑取反 !

2.逻辑与 &&

3.逻辑或 ||

4.短路

5.操作符的优先级和使用顺序(部分)

6.头文件

五、分支语句其二:switch 语句

1.switch 中的 break

2.switch 中的 default

六、三大循环 while、for、do-while

1.while 循环

2.for 循环

3.do-while 循环

4.如何选择循环

七、循环的至关:break 和 continue

1.continue 语句

2.break 语句

八、嵌套循环

九、goto 语句


正文开始

C语言是结构化的程序设计语言,这里的结构指的是顺序结构选择结构循环结构,C语言是能够实现这三种结构的,其实我们如果仔细分析,我们日常所见的事情都可以拆分为这三种结构或者这三种结构的组合。

我们可以使用 if、switch实现分支结构,使用 for、while、do-while实现循环结构。


一、分支语句其一 if else

1.if 语句

if 语句的语法如下

if (表达式)

    语句;

表达式成立(为真),则语句执行,表达式不成立(为假),则语句不执行。在C语言中,0为假,非0为真,也就是表达式的结果如果是0,则语句不执行,表达式的结果如果是非0,则语句执行。一个 if语句只能测试和执行一次

例:输入一个整数,判断是否为奇偶数

#include <stdio.h>

int main()
{
    int num = 0;
    scanf("%d", &num);
    if(num % 2 == 1)
        printf("%d 是奇数\n", num);
    return 0;
}

我们知道,偶数为2的倍数,但奇数不是,那么一个数如果除以2的余数是1的话,那么这个数就是奇数。在C中我们就以 num % 2 == 1表示,其中 == 在 if语句中表示是否等于。执行程序时,进入 if语句中的表达式判断真假。以上面判断奇偶数为例子,若 num % 2  的结果为1,那么就会执行表达式后面的语句,假若我们输入 3 ,就会输出如下结果:

3 % 2 的确是商1余1,那么表达式返回的结果就是1,那么 if将继续往下执行

若输出4,4是偶数,在这个程序中则什么都不输出:

4 % 2 的结果是商2余0,表达式返回的结果就是0,那么 if将中断程序,跳过紧跟其后面的语句,直接来到 if块外的语句(此例中为 return 0),程序继续执行直至结束。

那么 if语句可以总结成以下语块:

同时,if语句后面也可以囊括多个语句,多个语句结合在一起称为代码块

if (表达式)

{

    语句1;

    语句2;

    ...

    语句n;

}

2.else 语句 

上面我们知道,只有输入奇数后才返回结果肯定是达不到我们的预期效果的,这里就需要 else语句了,语法形式如下:

if (表达式)

    语句1;

else

    语句2;

那么判断一个数为奇偶数的代码就可以进行改善:

#include <stdio.h>

int main()
{
    int num = 0;
    scanf("%d", &num);
    if(num % 2 == 1)
        printf("%d 是奇数\n", num);
    else
        printf("%d 是偶数\n", num);
    return 0;
}

这时我们再分别输入 3 和 4 :

由上面我们可以知道:当输入3时进入 if语句,忽略 else语句;而输入4时进入 else语句,忽略 if 语句。if语句中的表达式为num % 2 == 1,那么相应的 else语句中默认的表达式应该与 if语句中的表达式相反,即 if语句和 else语句的表达式互补。在这个例子中实际上就是 num % 2 != 1。一个独立的 if-else语句有且只有一个语句生效(要么是 if,要么是 else)。

这样无论是输入奇数还是偶数,程序都会返回一个结果,就可以达到我们的预期。

if-else 语句同样也可以囊括多个代码:

if (表达式1)

{

    语句1;

    ....

    语句n;

}

else

{

    语句1;

    ....

    语句n;

}

/*练习*\  输入一个年龄,>= 18岁就输出:成年,否则就输出:未成年

#include <stdio.h>

int main()
{
    int age = 0;
    scanf("%d", &age);
    if(age>=18)
        printf("成年\n");
    else
        printf("未成年\n");
    return 0;
}

3.else if 语句

在 if-else 语句中,else 可以与另⼀个 if 语句连用,构成多重判断。 比如:要求输入⼀个整数,判断输入的整数是0,还是正数或者负数。请看如下代码:

#include <stdio.h>

int main()
{
    int num = 0;
    scanf("%d", &num);
    if(num == 0)
        printf("输⼊的数字是0\n");
    else if(num > 0)
        printf("输⼊的数字是正数\n");
    else
        printf("输⼊的数字是负数\n");
    return 0;
}

我们来分析一下这个程序:首先程序定义了一个变量 num,接下来运用scanf()函数来让我们输入一个数据赋给 num,接下来就进入了分支语句。如果我们输入的值是0,这个程序就会结束,不再运行第一个 if语句后的代码。如果我们输入的值是非零数,程序将忽略第一个 if语句,进入后面的代码。我们输入的是非0数,由题目我们知道还要判断数字的正负,那么,第一个 else就是对应 if(num == 0)这个语句。我们在上面提到过 if 和 else 都可以囊括多个语句,那么以上代码就等同于:

#include <stdio.h>

int main()
{
    int num = 0;
    scanf("%d", &num);
    if(num == 0)
        printf("输⼊的数字是0\n");
    else //num != 0
    {
        if(num > 0)
            printf("输⼊的数字是正数\n");
        else// num < 0
            printf("输⼊的数字是负数\n");
    }
    return 0;
}

​

如果 num是整数,则进入第二个 if语句;否则进入第二个 else语句。这里值得注意的是,第二个else语句的隐含条件本应是num <= 0,但是由于代码块外的 else的隐含条件是 num!=0,所以第二个 else语句条件中的范围不再包括0(以第一个 else作为前提)。这就是 else if语句。当然,本着C语言的简洁易懂的特点,在需要判断的条件大于等于3个时,我们大可不必写出类似上述代码。

/*练习*\  输入一个整数,如果是正数,再判断是奇数还是偶数,并输出;如果不是正数则输出:非正数。

#include <stdio.h>

int main()
{
    int num = 0;
    scanf("%d", &num);
    if(num>0)
    {
        if(num%2 == 0)
            printf("偶数\n");
        else
            printf("奇数\n");
    }
    else
    {
        printf("⾮正数\n");
    }
    return 0;
}

4.悬空 else 问题

如果有多个 if 和 else ,可以记住这样⼀条规则:else 总是跟最接近的 if 匹配,除非最近的 if 被花括号括起来我们首先从下面代码开始

#include <stdio.h>

int main()
{
    int a = 0;
    int b = 2;
    if(a == 1)
        if(b == 2)
            printf("hehe\n");
    else
        printf("haha\n");
 return 0;
}

程序运行的结果是啥?很多初学者,判断 a是0,不等于1,那就执行 else子句,打印 haha。但是当运行代码时,输出的结果是:啥都不输出:

上面的代码排版,让 else和第一个 if语句对齐,让我们以为 else是和第一个 if匹配的,当 if语句不成立的时候,自然想到的就是执行 else子句,打印 haha,但实际上 else是和第二个 if进行匹配的,这样后边的 if-else语句是嵌套在第一个 if语句中的,如果第⼀个 if语句就不成立,嵌套 if和 else就没机会执行了,最终啥都不打印。

如果代码改成下面这样就更加容易理解了:

#include <stdio.h>

int main()
{
    int a = 0;
    int b = 2;
    if(a == 1)
    {
        if(b == 2)
            printf("hehe\n");
        else
            printf("haha\n");
    }
    return 0;
}

或者如果我们希望 else确实和第一个 if匹配,可以这样修改代码:

#include <stdio.h>

int main()
{
    int a = 0;
    int b = 2;
    if(a == 1)
    {
        if(b == 2)
            printf("hehe\n");
    }
    else
    {
        printf("haha\n");
    }
    return 0;
}

只要带上适当的大括号,代码的逻辑就会更加的清晰,所以大家以后在写代码的时候要注意括号的使用,让代码的可读性更高。

二、关系操作符

C语言用于比较的表达式,称为关系表达式,里面使用的运算符就称为关系运算符。了解关系有操作符是我们学习分支循环语句的前提!关系操作符主要有下面6个。

> //大于运算符

< //小于运算符

== //相等运算符

>= //大于等于运算符

<= //小于等于运算符

!= //不相等运算符

在数学上,我们常常将两个数进行比较大小,例如 3 > 2,3 < 5,x > 6等等,这些被称为不等式,而两个数之间的符号称为不等号。我们可以看到这些不等式都由左右两个数或表达式和一个不等号构成。那么在C中,关系表达式也是由两个变量或表达式和一个关系操作符构成的,所以关系操作符是双目操作符

关系操作符主要用于分支语句和循环语句进行条件判断。由上面我们可以知道在C中0为假,非0为真,而分支语句运行与否取决于圆括号中表达式的值。表达式的值为非0值就运行;反之则不运行。那么我们可以得到:关系表达式的结果是一个具体的值!比如, 20 > 12 返回 1 , 12 > 20 返回 0 。

例:

if (x == 3)

{

    printf("%d\n", x);

}

这里要注意的是,数学上的等于号( = )一般有两种含义:第一种是将一个数赋值给一个变量,第二种是判断条件。但在C语言中,赋值和判断条件的符号是完全不同的无论是写法还是作用上。如果不慎将上列代码写成这样:

if (x = 3)

{

    printf("%d\n", x);

}

“x = 3”这个表达式表示的是将3赋值给变量x,而"x == 3"这个表达式表示的是x是否等于3。如果在 if语句圆括号中写出x = 3这个表达式,那么这个表达式的返回值会是3,3是非0值判断条件为真,那么无论如何这个 if语句总会执行块中的代码。如果在 if语句圆括号中写出x == 3这个表达式,这个表达式会检测变量x的值,如果x不等于3,返回值为0,块中的代码不会执行:反之,返回值为1,块中的代码会执行。

为了防止出现这种错误,有的程序员喜欢将变量写在等号的右边:

if (3 == x)...

这种写法没有问题,反而是我们值得学习的一种写法,如果在编写代码的过程中少输入了一个等号:

if (3 = x)...

在之前的博客中讲过,类似3 = x这种写法是没有意义的,编译器会直接报错,这样也可以节省检查代码的时间。

最最最重要的一点:在编写C程序运用关系操作符时严禁编写成数学上的写法!

三、条件操作符

条件操作符也叫三目操作符需要接受三个操作数,形式如下:

exp1 ? exp2 : exp3

条件操作符的计算逻辑是:如果 exp1 为真, exp2 计算的结果是整个表达式的结果;如果 exp1 为假, exp3 计算的结果是整个表达式的结果。

/*练习 1*\  使用条件操作符改造下面代码

#include <stdio.h>

int main()
{
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    if (a > 5)
        b = 3;
    else
        b = -3;
    printf("%d\n", b);
    return 0;
}

改造后:

#include <stdio.h>

int main()
{
    int a = 0;
    int b = 0;
    scanf("%d", &a);
    b = a>5 ? 3:-3;
    printf("%d\n", b);
    return 0;
}

/*练习 2*\  使用条件表达式实现找两个数中较大值

#include <stdio.h>

int main()
{
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    int m = a>b ? a : b;
    printf("%d\n", m);
    return 0;
}

四、逻辑操作符

C语言中有三种逻辑操作符,它们分别是&&(逻辑与)、||(逻辑或)、!(逻辑取反)。

1.逻辑取反 !

比如,我们有一个变量叫 flag,如果 flag为假,要做一个什么事情,就可以这样写代码:

#include <stdio.h>

int main()
{
    int flag = 0;
    if(!flag)
    {
        printf("do something\n");
    }
    return 0;
}

如果 flag为真,!flag就是假,如果 flag为假,!flag就是真。

所以上面的代码的意思就是 flag为假,判断条件时 !flag为真,因此执行 if语句中的代码。

2.逻辑与 &&

&&是与运算符,也是并且的意思,&&是一个双目操作符,使用的方式是a&&b,&&两边的表达 式都是真的时候,整个表达式才为真,只要有一个是假,则整个表达式为假。

比如,如果我们说3月到5月是春天,那使用代码该怎么体现呢?

int month = 0;

scanf("%d", &month);

if(month >= 3 && month <= 5)

{

    printf("春季\n");

}

这里表达的意思就是month既要大于等于3,又要小于等于5,必须同时满足。

3.逻辑或 ||

||是或运算符,也就是或者的意思, ||也是一个双目操作符,使用的方式是a || b,||两边的表达式只要有一个是真,整个表达式就是真,两边的表达式都为假的时候,才为假。

比如,我们说一年中12月或者1月或者2月是冬天,那么我们怎么使用代码体现呢?

int month = 0;

scanf("%d", &month);

if(month == 12 || month==1 || month == 2)

{

    printf("冬季\n");

}

/*练习*\  输入一个年份year,判断year是否是闰年。闰年判断的规则:

1. 能被4整除并且不能被100整除是闰年

2. 能被400整除是闰年

#include <stdio.h>

//代码1
int main()
{
    int year = 0;
    scanf("%d", &year);
    if(year%4==0 && year%100!=0)
    printf("是闰年\n");
    else if(year%400==0)
    printf("是闰年\n");
    return 0;
}

//代码2
int main()
{
    int year = 0;
    scanf("%d", &year);
    if((year%4==0 && year%100!=0) || (year%400==0))
    printf("是闰年\n");
    return 0;
} 

4.短路

C语言逻辑运算符还有⼀个特点:它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。

如前面的代码:

if(month >= 3 && month <= 5)

表达式中&&的左操作数是month >= 3,右操作数是month <= 5,当左操作数的结果是0的时候,即使不判断 month <= 5 ,整个表达式的结果也是0(不是春季)。

所以,对于&&操作符来说,左边操作数的结果是0的时候,右边操作数就不再执行

对于||操作符是怎么样呢?我们结合前面的代码:

if(month == 12 || month==1 || month == 2)

如果month == 12,则不用再判断month是否等于1或者2,整个表达式的结果也是1(是冬季)。 所以,||操作符的左操作数的结果不为0时,就无需执行右操作数

像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值

/*练习*\  阅读代码,计算代码输出的结果

#include <stdio.h>

int main()
{
    int i = 0,a=0,b=2,c =3,d=4;
    i = a++ && ++b && d++;
    //i = a++||++b||d++;
    printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
    return 0;
}

5.操作符的优先级和使用顺序(部分)

既然关系操作符、条件操作符和逻辑操作符也是操作符,那么它们也就有它们的优先级。我们可以对第一章所涉及到的 操作符的优先级和使用顺序表 进行优化升级:

操作符描述优先级(由上往下)
++后置++
--后置--
!逻辑反
+单目,表示正值
-单目,表示负值
++前置++
--后置--
sizeof取其长度,以字节表示
(类型)类型转换
*乘法
/除法

%

整数取余
+加法
-减法
>大于
>=大于等于
<小于
<=小于等于
==等于
!=不等于
&&逻辑与
||逻辑或
?:条件操作符
=赋值
+=以...加
-=以...减
*=以...乘
/=以...除
%=以...取模

/*操作符的优先级(部分)*\

6.头文件 <iso646.h>

C99标准新增了可代替逻辑运算符的拼写,它们被定义在<iso646.h>头文件中。如果在程序中包含该头文件,便可用and代替&&、or代替||、not代替!。为打好C语言基础,此头文件不建议萌新使用

***((((((如果不熟悉逻辑运算符或者觉得很别扭,请记住:(练习 && 时间) == 完美))))))***

五、分支语句其二:switch 语句

除了 if语句外,C语言还提供了 switch语句来实现分支结构。switch语句是⼀种特殊形式的 if-else结构,用于判断条件有多个结果的情况。它把多重的 else if改成更易用、可读性更好的形式。switch语句的形式如下:

switch (expression)

{

case value1:

    statement;

case value2:

    statement;

default:

    statement;

}

1.switch 中的 break

我们来看下列代码:

#include <stdio.h>

int main()
{
    int n = 0;
    scanf("%d", &n);
    switch(n%3)
    {
    case 0:
        printf("整除,余数为0\n"); 
        break;
    case 1:
        printf("余数是1\n"); 
        break;
    case 2:
        printf("余数是2\n"); 
        break;
    }
    return 0;
}

假如我们输入3的倍数,switch语句就会执行case 0这一语句;同样的输入形如3*n+1和3*n+2时switch语句会分别执行case 1和case 2语句。随后打印完对应的结果后执行 break语句就会跳出switch语句来到return 0,整个程序结束。若我们将每个 case语句后的 break删除会怎样呢?:

#include <stdio.h>

int main()
{
    int n = 0;
    scanf("%d", &n);
    switch(n%3)
    {
    case 0:
        printf("整除,余数为0\n"); 
    case 1:
        printf("余数是1\n"); 
    case 2:
        printf("余数是2\n"); 
    }
    return 0;
}

假若输入3:

我们可以观察到,除了会输出本应输出的结果,连case 1和case 2会输出的结果都会出现。那么输入1和2也应该是相同的道理。输入1则会输出case 1中的结果并输出case 2中的结果;输入2则只会输出case 2中的结果。出现这种情况的原因在于 switch语句也是分支效果的,只有在 switch语句中使用 break才能在跳出 switch语句,如果某一个 case语句的后边没有 break语句,代码会继续往下执行,并有可能执行其他 case语句中的代码,直到遇到 break语句或者 switch语句结束。就比如上面的代码就执行了case 1和case 2中的语句。

所以在 switch语句中 break语句是非常重要的,break语句能实现真正的分支效果。当然,也不是每个 case语句都得有,具体情况具体分析~

/*练习*\  输入1-5,输出的是“工作日” 输入6-7,输出“休息日”

#include <stdio.h>

int main()
{
    int day = 0;
    scanf("%d", &day);
    switch(day)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("⼯作⽇\n");
        break;
    case 6:
    case 7:
        printf("休息⽇\n");
        break;
    }
    return 0;
}

2.switch 中的 default

在使用 switch语句的时候,我们可能遇到一种情况,比如 switch后的表达式中的值无法匹配代码中的 case语句的时候,这时候要不就不做处理,要不就在 switch语句中加入 default子句。一个 switch语句中有且只能有一条 default子句

加入 default子句的 switch语句形式如下:

switch (expression)

{

case value1:

    statement;

case value2: 

    statement;

default:

    statement;

}

switch后边的 expression的结果不是 value1,也不是 value2的时候,就会执行 default子句。

比如前面的打印星期的练习,如果 day的输入不是1~7的值,如果我们要提示:输入错误。则可以这样完成代码:

#include <stdio.h>

int main()
{
    int day = 0;
    scanf("%d", &day); 
    switch(day)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("⼯作⽇\n");
        break;
    case 6:
    case 7:
        printf("休息⽇\n");
        break;
    default:
        printf("输⼊错误\n");
        break;
    }
    return 0;
}

根据表达式 expression不同的值,执行相应的 case分支。如果找不到对应的值,就执行 default分支。switch语句必须遵循以下规则:

switch语句中的 expression是一个常量表达式(包括char类型),必须是一个整型枚举类型

在一个 switch 中可以有任意数量的 case语句。每个 case后跟一个要比较的值和一个冒号。

case的 constant-expression必须与 switch中的变量具有相同的数据类型,且必须是一个常量整型常量表达式

当被测试的变量等于 case中的常量时,case后跟的语句将被执行,直到遇到 break语句为止。

当遇到 break语句时,switch终止,控制流将跳转到 switch语句后的下一行。

不是每一个 case都需要包含 break。如果 case语句不包含 break,控制流将会继续执行后续的 case,直到遇到 break为止。

一个 switch语句可以有一个可选的 default,出现在 switch的结尾。default 可用于在上面所有 case都不为真时执行一个任务。default 中的 break语句不是必需的

由于 default子句和 case语句在 switch语句中是并列存在的,所以他们并没有严格的顺序先后,但一般情况下我们都会将 default子句写在 switch语句中的最后,让 case语句排在前面。

六、三大循环 while、for、do-while

1.while 循环

while循环的形式与 if语句类似,它的形式如下:

while(表达式)

    语句;//如果循环体想包含更多的语句,可以加上大括号

它与 if语句不仅形似,也神似。我们在前面就已经知道,if语句运行的前提就是其表达式是否为真(非0)。while循环也是同样的道理,如果表达式的值为非0,那么就会执行其内部的语句;反之,则不会执行。它们都会首先检测表达式的真假!但与 if语句本质的差别就在于 while循环会一直重复着表达式真假的判断,然后一直重复着其内部的语句。如果表达式的值一直为真,它就会一直运行下去(死循环);一旦表达式的值为假,它就不再执行内部的代码,就会跳出 while循环,继续执行下面的语句。每一次循环都被称为一次迭代

***希望各位的爱情观也像 while循环一样 祝愿长久 学会止损***

因此在构建 while循环时,为其附加一个限制条件是非常有必要的!那我们应该如何限制条件呢?

首先我们可以运用在前面提到过的关系条件逻辑操作符或其结合来限制其条件。

其次我们也可以使用运算符来限制条件。运算符既可以在表达式中出现,也可以在内部的语句中出现。出现在表达式中会首先进行一次运算后再进行条件判断;出现在内部语句中每次迭代都会进行一次运算。

/*练习*\  在屏幕上打印 1~10

#include <stdio.h>

int main()
{
    int i = 1;
    while(i<=10)
    {
        printf("%d ", i);
        i = i+1;
    }
    return 0;
}

/*练习*\  输入一个正整数,逆序打印这个整数的每一位

#include <stdio.h>

int main()
{
    int n = 0;
    scanf("%d", &n);
    while(n)
    {
        printf("%d ", n%10);
        n /= 10;
    }
    return 0;
}

2.for 循环

for循环是三种循环中使用最多的,for循环的语法形式如下:

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

    语句;//如果循环体想包含更多的语句,可以加上大括号

表达式1是初始化部分,用于循环变量的初始化,只会在循环开始时执行一次。表达式1也可以使用printf()函数。

表达式2是条件部分,在执行循环之前对表达式2求值,用于循环结束条件的判断。为0退出循环;为非0执行循环。

表达式3是调整部分,用于循环变量的调整,在每次循环结束时求值。

这些表达式也叫控制表达式,都是完整表达式,所以每个表达式的副作用都发生在对下一个表达式求值之前。可以省略1~3个表达式(小心死循环),但是表达式之间的分号不可省略

/*练习*\  在屏幕上打印1~10

#include <stdio.h>

int main()
{
    int i = 0;
    for(i=1; i<=10; i++)
    {
        printf("%d ", i);
    } 
    return 0;
}

for和 while在实现循环的过程中都有初始化、判断和调整这三个部分,但是 for循环的三个部分非常集中,便于代码的维护。而如果代码较多的时候 while循环的三个部分就比较分散,所以从形式上 for循环要更优⼀些。

/*练习*\  计算1~100之间3的倍数的数字之和

#include <stdio.h>

int main()
{
    int i = 0;//用于统计3的倍数
    int sum = 0;//用于计算和
    for(i=3; i<=100; i+=3)
    {
        sum += i;
    }
    printf("%d\n", sum);
    return 0;
}

3.do-while 循环

do-while循环又被称为出口条件循环。在循环语句中 do-while语句的使用最少,它的语法如下:

do

    语句;//如果循环体想包含更多的语句,可以加上大括号

while(表达式);//分号不可省略!!!

while和 for这两种循环都是先判断,条件如果满足就进入循环,执行循环语句,如果不满足就跳出循环;而 do-while循环则是先执行一次循环语句,然后进行 while表达式的判断。表达式为真就会进行下一次,表达式为假则不再继续循环。

/*练习*\  在屏幕上打印1~10

#include <stdio.h>

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

/*练习*\  输入一个正整数,计算这个整数是几位数

#include <stdio.h>

int main()
{
    int n = 0;
    scanf("%d", &n);
    int cnt = 0;
    do
    {
        cnt++;
        n /= 10;
    } while (n);
    printf("%d\n", cnt);
    return 0;
}

4.如何选择循环

如何选择使用哪种循环?首先确定是需要入口条件循环还是出口条件循环。通常入口条件循环的使用频率比较多,有几个原因:其一,一般原则是在执行循环之前先测试条件比较好,这样可以更加安全地编写和执行代码;其二,测试放在循环的开头,程序的可读性就更高。另外在许多应用中,要求在一开始不满足测试条件时就直接跳过整个循环。

那么,假设需要一个入口条件循环,是用 for循环还是 while循环?这取决于个人喜好,因为二者皆可,要让 for循环看起来像 while循环,可以省略第一个和第三个表达式。要让 while循环看起来像 for循环,可以在 while循环前面初始化变量,并在 while循环体中包含更新语句。一般而言,当循环涉及初始化更新变量时,用 for循环就更为合适,而在其他条件下则用 while循环就更好。

七、循环的至关:break 和 continue

一般而言,程序进入循环后,在下一次循环测试之前会执行完循环体中的所有语句。continue和 break语句可以根据循环体中的测试结果来忽略一部分循环内容,甚至结束循环。

break的作用是用于永久的终止循环,只要 break被执行就会直接跳出循环继续往后执行。

continue的作用是跳过本次循环continue后边的代码,在 for循环和 while循环中有所差异。

break和 continue一般结合 if语句进行使用。

1.continue 语句

3种循环都可以使用continue语句。执行到该语句时会跳过本次迭代的剩余部分,并开始下一轮的迭代。话不多说,直接举例:

#include <stdio.h>

int main()
{
    int i = 1;
    while(i<=10)
    {
        if(i == 5)
            continue;
    //当i等于5后,就执⾏continue,直接跳过continue的代码,去循环的判断的地⽅
    //因为这⾥跳过了i = i+1,所以i⼀直为5,程序陷⼊和死循环
        printf("%d ", i);
        i = i+1;
    }
    return 0;
}
#include <stdio.h>

int main()
{
    int i = 1;
    for(i=1; i<=10; i++)
    {
        if(i == 5)
            continue;//这⾥continue跳过了后边的打印,来到了i++的调整部分
        printf("%d ", i);
    }
    return 0;
}
#include <stdio.h>

int main()
{
    int i = 1;
    do
    {
        if(i == 5)
            continue;
        printf("%d ", i);
        i = i + 1;
    } while(i<=10);
    return 0;
}

以上代码自行理解体会,这里不再过多解释

假若要避免使用 continue语句,有两种方法:第一种是省略 continue语句,将剩余部分放在一个else块中;第二种是将原来的 if语句中的条件的关系反过来。例如上面代码 if表达式为 i == 5,反过来就是i !=5。

2.break 语句

程序执行到循环中的 break语句时,会终止包含它的循环,并继续执行下一阶段。话不多说,直接举例:

#include <stdio.h>

int main()
{
    int i = 1;
    while(i<=10)
    {
        if(i == 5)
            break;//当i等于5后,就执⾏break,循环就终⽌了
        printf("%d ", i);
        i = i+1;
    }
    return 0;
}
#include <stdio.h>

int main()
{
    int i = 1;
    for(i=1; i<=10; i++)
    {
        if(i == 5)
            break;
        printf("%d ", i);
    }
    return 0;
}
#include <stdio.h>

int main()
{
    int i = 1;
    do
    {
        if(i == 5)
            break;
        printf("%d ", i);
        i = i + 1;
    } while(i<=10);
    return 0;
}

以上代码自行理解体会,这里不再过多解释

八、嵌套循环

前面学习了三种循环 while,do-while,for,这三种循环往往会嵌套在⼀起才能更好的解决问题,就是我们所说的:循环嵌套。嵌套循环含有外层循环内层循环两种。这里我们就看一个例子。

/*练习*\  找出100~200之间的素数,并打印在屏幕上。

题目解析

1. 要从100~200之间找出素数,首先得有100~200之间的数,这里可以使用循环解决。

2. 假设要判断i是否为素数,需要拿2~i-1之间的数字去试除i,需要产生2~i-1之间的数字,也可以使用循环解决。

3. 如果2~i-1之间有数字能整除i,则i不是素数,如果都不能整除,则i是素数。

#include <stdio.h>

int main()
{
    int i = 0;
    //循环产⽣100~200的数字
    for(i=100; i<=200; i++)
    {
    //判断i是否为素数
    //循环产⽣2~i-1之间的数字
    int j = 0;
    int flag = 1;//假设i是素数
    for(j=2; j<i; j++)
    {
        if(i % j == 0)
        {
            flag = 0;
            break;
        }
    }
    if(flag == 1)
        printf("%d ", i);
    }
    return 0;
}

上面代码中,负责循环产生100~200的数字的循环我们称为外层循环,而负责判断i是否为负数并循环产生2~i-1之间的数字的循环我们称为内层循环。嵌套循环中的内层循环在每次外层循环迭代时都会被执行一次。内层循环中的 break只会让程序跳出包含它的当前循环,要跳出外层循环还需要一个 break; continue也是如此。

一层循环的可以大大提高编写C程序的效率,而嵌套循环更是锦上添花,合理使用嵌套循环能写出很多不可思议的代码。

九、goto 语句

C语言提供了一种⾮常特别的语法,就是goto语句跳转标号(标签名), goto 语句可以实现在同一个函数跳转到设置好的标号处。标签名命名规则遵循变量名命名规则。它的使用例子如下:

#include <stdio.h>

int main()
{
    printf("hehe\n");
    goto next:
    printf("haha\n"); 
next:
    printf("跳过了haha的打印\n"); 
    return 0;
}

原则上,根本不需要在C中使用 goto语句,goto语句是一个危险的语句。goto语句如果使用不当,就会导致在函数内部随意乱跳转,打乱程序的执行流程,所以我们的建 议是能不用就尽量不去使用;但是 goto语句也不是一无是处,在多层循环的代码中,如果想快速跳出,使用 goto就非常方便了。

for(...)

{

    for(...)

    {

        for(...)

        {

            if(disaster)

                goto error;

        }

    }

}

error: //...

本来 for循环想提前退出得使用 break,一个 break只能跳出一层 for循环,如果3层循环嵌套就得使用3个 break才能跳出循环,所以在这种情况下我们使用 goto语句就会更加的快捷。


以上就是C语言中较为重要的板块——分支与循环。有了分支语句和循环语句,编写出来的C程序的执行效率会大大提高。

  • 32
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值