分支和循环

目录

1.if语句

1.1 if

1.2 else

1.3 分支中包含多条语句

1.4 嵌套if

1.5 悬空else问题

2. 关系操作符

3. 条件操作符

4. 逻辑操作符:&& , || , !

4.1 逻辑取反运算符 !

4.2 逻辑与运算符

4.3 逻辑或运算符

4.4 练习:闰年的判断

4.5 短路

5. switch 语句

5.1 if语句和switch语句的对比

5.2 switch语句中的break

5.3 switch语句中的default

5.4 switch语句中的case和default的顺序问题

6. while循环

6.1 if 和 while的对比

6.2 while 循环的实践

7. for循环

7.1 语法形式

7.2 for循环的执行流程

7.3 for循环的实践

8. do-while 循环

8.1 语法形式

8.2 do while循环的执行流程

8.3 do while循环的实例

9. break和continue语句

9.1 while循环中的break和continue

9.1.1 break举例

9.1.2 continue举例

9.2 for循环中的break和continue

9.2.1 break 举例

9.2.2 continue举例

10. goto 语句


1.if语句

1.1 if

if 语句的语法形式如下:

if ( 表达式 )
         语句

表达式成立(为真),则语句执行,表达式不成立(为假),则语句不执行。

在C语言中,0为假,非0表示真,也就是表达式的结果如果是0,则语句不执行,表达式的结果如果不是0,则语句执行。
例子:输入一个整数,判断是否为奇数

#include <stdio.h>
int main()
{
    int num = 0;
    scanf("%d", &num);
    if(num % 2 == 1)
    printf("%d 是奇数\n", num);
    return 0;
}

1.2 else

如果一个数不是奇数,那就是偶数了,如果任意一个整数,我们要清楚的判断是奇数还是偶数怎么表示呢?
这里就需要ifelse 语句了,语法形式如下:

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;
}

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

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

1.3 分支中包含多条语句

#include <stdio.h>
int main()
{
    int age = 0;
    scanf("%d", &age);
    if(age >= 18)
        printf("成年了\n");
        printf("可以谈恋爱了\n");
    return 0;
}

上面的代码,你会发现输入的值不管是>=18 还是<18,"可以谈恋爱了" 都会打印在屏幕上。

这是因为if 语句只能控制一条语句,就是printf("成年了\n"); ,if语句为真,则打印成年了,
if语句为假,则不打印,对于printf("可以谈恋爱了\n"); 是独立存在的,不管if语句的条件的真
假,都会被执行。那如果我们要if语句同时控制2条语句,怎么办呢?那就要使用 {} 将代码括起来,
else 后也可以跟上大括号。如下:

include <stdio.h>
int main()
{
    int age = 0;
    scanf("%d", &age);
    if(age >= 18) //if 后使用{} 控制多条语句-这个块也叫:程序块,或者复合语句
    {
        printf("成年了\n");
        printf("可以谈恋爱了\n");
    }
    return 0;
}
#include <stdio.h>
int main()
{
    int age = 0;
    scanf("%d", &age);
    if(age >= 18) //if 后使用{} 控制多条语句-这个块也叫:程序块,或者复合语句
    {
        printf("成年了\n");
        printf("可以谈恋爱了\n");
    }
    else //else 后使用{}控制多条语句-这个块也叫:程序块,或者复合语句
    {
        printf("未成年\n");
        printf("不可以早恋哦\n");
    }
    return 0;
}

1.4 嵌套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) //这里的if 相当于嵌套在else语句中,形成了嵌套结构
        printf("输入的数字是正数\n");
    else
        printf("输入的数字是负数\n");
    return 0;
}

上图中橙色背景的代码就是嵌套在前面的else 子句中的,构成了嵌套的if语句。
再比如:
输入一个整数,如果是正数,再判断是奇数还是偶数,并输出;如果不是正数则输出:非正数。

#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;
}

以上就是嵌套if语句的语法,有了嵌套if语句,就可以完成更多复杂逻辑的判断。

1.5 悬空else问题

如果有多个if 和else ,可以记住这样一条规则, 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;
}

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

这就是悬空else 的问题,如果有多个if 和else ,可以记住这样一条规则, else 总是跟最接近
的if 匹配。
上面的代码排版,让else 和第一个if 语句对齐,让我们以为else 是和第一个if匹配的,当if
语句不成立的时候,自然想到的就是执行 else 子句,打印haha ,但实际上else 是和第二个if
进行匹配的,这样后边的if...else 语句是嵌套在第一个if 语句中的,如果第一个if 语句就不
成立,嵌套if 和else 就没机会执行了,最终啥都不打印。
如果代码改成下面这样就更加容易理解了

2. 关系操作符

C 语言用于比较的表达式,称为 “关系表达式”(relational expression),里面使用的运算符就称
为“关系运算符”(relational operator),主要有下面6个。

  • > 大于运算符
  • < 小于运算符
  • >= 大于等于运算符
  • <= 小于等于运算符
  • == 相等运算符
  • != 不相等运算符

下面是一些例子

a == b;
a != b;
a < b;
a > b;
a <= b;
a >= b;

关系表达式通常返回0 或1 ,表示真假。
C 语言中, 0 表示假,所有非零值表示真。比如, 20 > 12 返回1 , 12 > 20 返回0 。
关系表达式常用于if 或while 结构。

if (x == 3) 
{
    printf("x is 3.\n");
}

注意:相等运算符== 与赋值运算符= 是两个不一样的运算符,不要混淆。有时候,可能会不小心写
出下面的代码,它可以运行,但很容易出现意料之外的结果。

if (x = 3) ...

上面示例中,原意是x == 3 ,但是不小心写成x = 3 。这个式子表示对变量x 赋值3 ,它的返
回值为3 ,所以if 判断总是为真。
为了防止出现这种错误,有的程序员喜欢将变量写在等号的右边

if (3 == x) ...

这样的话,如果把== 误写成= ,编译器就会报错。

/* 报错 */
if (3 = x) ...

另一个需要避免的错误是:多个关系运算符不宜连用

3. 条件操作符

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

exp1 ? exp2 : exp3

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

练习1:使用条件操作符表示下面代码的逻辑

#include <stdio.h>
int main()
{
    int a = 0;
    int b = 0;
    scanf("%d", &a);
    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;
}

4. 逻辑操作符:&& , || , !

逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,主要有下面三个运算符。
• ! :逻辑取反运算符(改变单个表达式的真假)。
• && :逻辑与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。
• || :逻辑或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假)。
注:C语言中,非0表示真,0表示假

4.1 逻辑取反运算符 !

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

#include <stdio.h>
int main()
{
    int flag = 0;
    if(!flag)
    {
        printf("do something\n");
    }
    return 0;
}

如果flag 为真, !flag 就是假,如果flag 为假, !flag 就是真
所以上面的代码的意思就是flag 为假,执行if语句中的代码.

4.2 逻辑与运算符

&& 就是与运算符,也是并且的意思, && 是一个双目操作符,使用的方式是a&&b , && 两边的表达式都是真的时候,整个表达式才为真,只要有一个是假,则整个表达式为假。
比如:如果我们说月份是3月到5月,是春天,那使用代码怎么体现呢?

int month = 0;
scanf("%d", &month);
if(month >= 3 && month <= 5)
{
    printf("春季\n");
}

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

4.3 逻辑或运算符

|| 就是或运算符,也就是或者的意思, || 也是一个双目操作符,使用的方式是a || b , ||
两边的表达式只要有一个是真,整个表达式就是真,两边的表达式都为假的时候,才为假。
比如:我们说一年中月份是12月或者1月或者2月是冬天,那么我们怎么使用代码体现呢?

int month = 0;
scanf("%d", &month);
if(month == 12 || month==1 || month == 2)
{
    printf("冬季\n");
}

4.4 练习:闰年的判断

输入一个年份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.5 短路

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

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

表达式中&& 的左操作数是month >= 3 ,右操作数是month <= 5 ,当左操作数month >= 3 的
结果是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. switch 语句

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

switch (expression) {
    case 
        value1: statement
    case 
        value2: statement
    default:
        statement
}

上面代码中,根据表达式expression 不同的值,执行相应的case 分支。如果找不到对应的值,
就执行 default 分支。

注:
• switch 后的expression 必须是整型表达式
• case 后的值,必须是整形常量表达式

5.1 if语句和switch语句的对比

练习:输入任意一个整数值,计算除3之后的余数
如果使用if语句完成,如下:

#include <stdio.h>
int main()
{
    int n = 0;
    scanf("%d", &n);
    if(n%3 == 0)
        printf("整除,余数为0\n");
    else if(n%3 == 1)
        printf("余数是1\n");
    else
        printf("余数是2\n");
    return 0;
}

如果使用switch语句改写,就可以是这样的:

#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;
}

上述的代码中,我们要注意的点有:
1. case 和后边的数字之间必须有空格
2. 每一个case 语句中的代码执行完成后,需要加上break ,才能跳出这个switch语句。

5.2 switch语句中的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;
}

switch 语句也是分支效果的,只有在switch 语句中使用 break 才能在跳出switch 语
句,如果某一个case 语句的后边没有break 语句,代码会继续往下执行,有可能执行其他case
语句中的代码,直到遇到break 语句或者switch 语句结束。就比如上面的代码就执行了case
2 中的语句。
所以在switch 语句中break 语句是非常重要的,能实现真正的分支效果。
当然, break 也不是每个case 语句都得有,这就得根据实际情况来看了。

5.3 switch语句中的default

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

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;
}

5.4 switch语句中的case和default的顺序问题

在switch 语句中case 子句和default 子句有要求顺序吗? default 只能放在最后吗?
其实,在switch 语句中case 语句和default 语句是没有顺序要求的,只要你的顺序是满足实
际需求的就可以。
不过我们通常是把default 子句放在最后处理的。

6. while循环

C语言提供了3种循环语句, while 就是其中一种,接下来就介绍一下while 语句。
while 语句的语法结构和if 语句非常相似。

6.1 if 和 while的对比

if(表达式)
    语句;
while(表达式)
    语句;//如果循环体想包含更多的语句,可以加上大括号

你可以对比来看一下,具体写个代码吧

//代码1
#include <stdio.h>
int main()
{
    if(1)
        printf("hehe\n"); //if后边条件满足,打印一次hehe
    return 0;
}
//代码2
#include <stdio.h>
int main()
{
    while(1)
        printf("hehe\n"); //while后边的条件满足,死循环的打印hehe
    return 0;
}

这就是他们的区别,while语句是可以实现循环效果的。

6.2 while 循环的实践

练习:在屏幕上打印 1~10 的值

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

7. for循环

7.1 语法形式

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

for(表达式1; 表达式2; 表达式3)
    语句;//如果循环体想包含更多的语句,可以加上大括号

表达式1 用于循环变量的初始化
表达式2 用于循环结束条件的判断
表达式3 用于循环变量的调整

7.2 for循环的执行流程

首先执行 表达式1 初始化循环变量,接下来就是执行 表达式2 的判断部分, 表达式2 的结果如果
==0,则循环结束; 表达式2 的结果如果!=0则执行循环语句,循环语句执行完后,再去执行表达式3 ,调整循环变量,然后再去表达式2 的地方执行判断, 表达式2 的结果是否为0,决定循环是否继续。
整个循环的过程中,表达式1初始化部分只被执行1次,剩下的就是表达式2、循环语句、表达式3在循环。

7.3 for循环的实践

练习:在屏幕上打印1~10的值

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

8. do-while 循环

8.1 语法形式

do
    语句;
while(表达式);

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

8.2 do while循环的执行流程

在do while 循环中先执行图上的“语句”,执行完语句,在去执行“判断表达式”,判断表达式的
结果是!=0,则继续循环,执行循环语句;判断表达式的结果==0,则循环结束。
所以在do while 语句中循环体是至少执行一次的,这是do while 循环比较特殊的地方。

8.3 do while循环的实例

在屏幕上打印1~10的值

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

一般do while 使用在循环体至少被执行一次的场景下,所以较少一些。

9. break和continue语句

在循环执行的过程中,如果某些状况发生的时候,需要提前终止循环,这是非常常见的现象。C语言中
提供了break 和continue 两个关键字,就是应用到循环中的。

  •  break 的作用是用于永久的终止循环,只要break 被执行,直接就会跳出循环,继续往后行。
  • continue 的作用是跳过本次循环中continue 后边的代码,在for 循环和while 循环中有所差异的。

9.1 while循环中的break和continue

9.1.1 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;
}

打印了1,2,3,4后,当i等于5的时候,循环在break 的地方终止,不再打印,不再循环。
所以break 的作用就是永久的终止循环,只要break 被执行, break 外的第一层循环就终止了。
那以后我们在循环中,想在某种条件下终止循环,则可以使用 break 来完成我们想要的效果。

9.1.2 continue举例

continue 是继续的意思,在循环中的作用就是跳过本次循环中continue 后边的代码,继续进行
下一次循环的判断。
上面的代码,如果把break 换成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;
}

到这里我们就能分析出来, continue 可以帮助我们跳过某一次循环continue 后边的代码,直接
到循环的判断部分,进行下一次循环的判断,如果循环的调整是在continue 后边的话,可能会造成
死循环。

9.2 for循环中的break和continue

9.2.1 break 举例

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

9.2.2 continue举例

#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;
}

10. goto 语句

C语言提供了一种非常特别的语法,就是goto 语句跳转标号, goto 语句可以实现在同一个函数
内跳转到设置好的标号处。

#include <stdio.h>
int main()
{
    printf("hehe\n");
    goto next;
    printf("haha\n");

 next:
    printf("跳过了haha的打印\n");
    return 0;
}

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

for(...)
{
    for(...)
    {
        for(...)
        {
            if(disaster)
                goto error;
        }
    }
}
error:

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

posted @ 2024-10-13 12:45  写代码的大学生  阅读(3)  评论(0编辑  收藏  举报  来源