Files
BlogPosts/Collection/YoudaoyunNotes/02C语言/05-控制与分支.md

380 lines
11 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 一、分支控制
1. **二路分支**
- if...else语句
- 执行逻辑:非此即彼
![](images/WEBRESOURCE22d41843cc2f8e164fc5c3cd6753c92fimage.png)
![](images/WEBRESOURCEa9b36a9ebb8b287ddf16ffd2c09976d5image.png)
- 语法形式
```c
if( expression ) // 当 expression为一个条件表达式当为真时 执行 statements 1
{
statements 1
}
else // 当 expression 为假时, 执行 statements 2
{
statements 2
}
// 或
if( expression ) // 当 expression 为真时, 执行 statements 1
{
statements 1
}
```
1. **多路分支**
- **if...else多重嵌套**
- 表达一种多个选项中选择一个条件执行当前面的条件满足后面的if...else直接跳过当没有条件满足时则执行最后的else多选一。
![](images/WEBRESOURCE14ccf6590f7f4016b1afdcb6b9f04f4dimage.png)
- **if语句单独使用多次**
- 表达一种多种条件种选择执行的逻辑前面的if语句满足条件执行后面的if继续判断执行多选多或多选一。
![](images/WEBRESOURCEa492c1ba1be94ca9886a50ce9884cbc8image.png)
- **注意:**
- else语句只与前面最近且同级的if配套并且else不能单独使用。
- 若if语句或else语句中需要执行的代码只有一条语句则{}花括号可以省略,其他情况下{}花括号不能省略否则只有第1条语句属于if...else语句中
- **switch...case语句**
- 执行逻辑:根据选项选择不同的代码段进行执行
- 语法形式:
```c
switch(选择语句)
{
case 选项1:
break;
case 选项2:
break;
...
case 选项n:
break;
default:
break;
}
```
- 表达多个选项中选择一个进行执行
![](images/WEBRESOURCEaa39bdca22d940a0bb7d172aabd9a55dimage.png)
- **注意**
- switch语句中的选择语句必须是整数(整型、字符型、布尔型、枚举型、变量、 运算表达式甚至是函数调用case 语句中的选项必须是整型常量或char 型常量const 型变量都不行, 例如case 'w'
![](images/WEBRESOURCE4552fb76ccd7d5818b2a9d3abcf0061bimage.png)
- break语句是switch语句的结束标志。
- 一旦case选项匹配成功则立即执行其对应的语句直至遇到break语句。
- 不是所有的case语句都得加break语句但如果case语句后没有break语句则会无条件向下执行其他case语句直至遇到break语句或到switch语句的}花括号结束。
- default默认选项语句可以写也可以不写可以放在case的末尾也可放case最前或case语句选项的中央当所有的case选项都不匹配时则会执行dafault语句后的代码块
- case语句后可以为空语句如case 1:
## 练习
1. 编写程序实现,从键盘输入三个数从小到大输出到终端
1. 编写程序实现,从键盘输入一个字符串,将输入的大写字符转换为小写字母,小写字母转换为大写字母输出。
1. 从键盘输入一个数(0~15),将其输出为16进制数
## 作业
1. 从键盘输入一个字符串,统计输入的字符串中的大写字母、小写字母、数字、其他字符的个数【使用if语句和switch语句分别实现】
- **直接跳转**
- goto语句通常被告诫不要使用由于 goto 语句是一种无条件的直接跳转,有时甚至还会破坏程序的栈逻辑,因此不推荐使用,但是当我们在编写程序错误处理代码的时候,又会经常用到它,这是因为当程序发生错误时通常报告错误和及时退出比保护程序逻辑更加重要,并且 goto 语句可以忽视嵌套包裹它的任何代码块,直接跳转到错误处理单元。
```c
#include <stdio.h>
/* 除了出错处理其它情况一概不推荐使用goto因为goto会直接跳转到标签位置使得程序难以追踪难以阅读和修改 */
int main(int argc, char *argv[])
{
    printf("[%d]\n", __LINE__);
     goto globle;  // 往后跳
lable:   // 标签
    printf("[%d]\n", __LINE__);
    goto lable;  // 往前跳
globle:
    printf("[%d]\n", __LINE__);
    return 0;
}
/* 推荐使用场景 */
int main(void)
{
 // 初始化LCD
        goto lcd_err;
    // 初始化触摸屏
        // 出错 则需要释放LCD资源
        goto ts_err;
    // 开启采集环境温湿度
        // 出错 则需要释放LCD资源和触摸屏资源
        goto ht_err;
    // 获取环境光照
        // 出错 则需要释放LCD资源、触摸屏资源、温湿度模块资源
        goto light_err;
    // ....
light_err:
    ht_free();
ht_err:
    ts_free();
ts_err:
    lcd_free();
lcd_err:
    return 0;
}
```
# 二、循环控制
- **while语句**
```c
while(expression)
{
statements;
}
```
expression 可以是任意表达式C 语言中任何表达式都有一个确定的值), while语句根据表达式 expression 的值来决定是否执行下面的 statement被执行的这些语句也叫循环体 可以是一句简单的语句<可省略花括号> 也可以是用花括号括起来的若干条语句组合起来的复合语句<必须使用花括号包含> 如果 expression 的值为假则跳过 statement 如果为真则执行 statement 执行完了再来判断 expression 的值, 不断循环一直到其值为假为止(如果 expression 的值始终为真,则称为死循环或无限循环<Linux中可用ctrl+c强制退出程序>
![](images/WEBRESOURCE64848ec6b188f4b800d87151f5fdec76image.png)
👍
> Linux 的 C 代码风格中, 循环体结构(包括 while、 do…while 和 for 循环)的左花括号既可以写在循环语句的末尾, 也可以单独占一行, 如上述代码所示。 而对于函数而言, 包含函数体的左花括号一般单独占一行。 另外一定要注意缩进, 缩进的目的是为了增强代码的可读性, 在函数体、 循环结构、 分支结构等逻辑相对独立的代码块中都需要有适当的缩进。 每一层代码块推荐用 8 个空格来缩进, 过小则不易区分各个代码块, 在程序嵌套太深时也不能更好地起提醒作用。 当然如果并不经常用不同的编辑器来编辑代码, 用制表符代替空格也未尝不可, 毕竟敲多个空格键比较繁琐(如果需要用不同的编辑器编辑代码的话, 不同的编辑器可能对制表符的解释有所不同, 这就会导致在一款编辑器中显示正常的代码在另一款编辑器中却显示不正常) 。代码良好的可读性和易维护性庞大的工程中显得尤为重要, 因此良好的习惯必须在一开始写简单代码的时候就要养成。
```c
#include <stdio.h>
int main(int argc, char *argv[])
{
    int a;
    scanf("%d", &a);
    // while (a > 0)
    while (a)  // a的值非0 0
    {
        printf("%d ", a);
        a--;
    }
    printf("\n");
   
    return 0;
}
```
- **do...while语句**
```c
do{
statements;
}while(expression);
```
与while 循环类似, 根据表达式中的值来决定是否执行循环体, 区别是 do…while 循环不是先计算表达式, 而是先执行循环体在计算表达式的值, 因此它也被称为退出条件循环,即在每次执行循环体之后再检查判断条件, 这样
![](images/WEBRESOURCEe033a13a5da4e1bb7bc6f275fb254dfaimage.png)
```c
#include <stdio.h>
int main(int argc, char *argv[])
{
    int a;
    scanf("%d", &a);
    do{   // 至少执行一次循环体语句
        printf("%d ", a);  // 先执行循环体
        a--;
    }while (a); // 再进行判断条件是否为真(非0),为真则继续执行循环体中的语句,否则结束循环
    printf("\n");
   
    return 0;
}
```
- **for语句**
for 循环是一种更为灵活的循环结构, 在 Linux 内核中出现的频率大约是 while 循环和do…while 循环的四到五倍
```c
for(initialize; test; update)
{
statement;
}
```
语句块 statement 跟上两种循环体一样, 可以是单条语句也可以是用花括号括起来的复合语句。 关键字 for 之后的圆括号中包含有三个表达式, 第一个表达式initialize一般用来初始化循环控制变量 第二个表达式test一般用作循环测试条件 而第三个表达式update则一般用来更新循环控制变量 但从语法角度上讲它们可以是任意的语句,这些表达式可以是一个表达式或多个表示式(用逗号隔开)
for循环语句的执行流程是
1. 如果有initialize语句则执行它 然后执行test语句如果没有initialize语句则直接执行test语句。
1. 如果有test语句且其值为真或者没有该语句则执行语句statement循环体如果有 test 语句且其值为假则跳出for循环语句。
1. 执行循环体语句 statement 完成后执行update语句。
1. 如果有 update 语句则执行它, 然后跳到第 2 步test 语句, 如果没有 update 语句则直接跳到第 2 步test 语句。
```c
#include <stdio.h>
int main(int argc, char *argv[])
{
    for (int i = 0; i < 10; i++) /* 循环变量定义初始化赋值语句的写法int i = 0;是C99以后支持的
                                    老版编译器默认未采用c99标准则编译指令末尾添加-std=c99*/
    {
        printf("%d ", i);
    }
    printf("\n");
    return 0;
}
```
## 练习
1. 编写代码计算1~1000所有奇数的和【三种循环编写】
![](images/WEBRESOURCEddc658c0cce70a5068ad13c1c7567ac8image.png)
1. 计算1^2+2^2+...+n^2
![](images/WEBRESOURCE61673478243ea23a81ca7bed0da28733image.png)
1. 计算n的阶乘
- **break、continue与return语句**
- **break语句**
- 用于循环语句中时表示跳出当前循环(会结束循环)
- 用于switch语句时表示跳出switch语句
```c
for()
{
while()
{
do{
switch()
{
break;// 结束switch语句
}
break; // 结束do...while
} while();
break; // 结束while
}
break; // 结束for
}
```
- **continue语句**
- 只用于循环语句中,表示结束本次循环,进行下次循环
![](images/WEBRESOURCE459a0a24ac6047112d1d6479e8858315image.png)
- **return语句**
- 表示当前这个函数的结束
- **无限循环**
- 循环条件恒为真
```c
while(1);
for(;;);
do{}while(1);
```
## 练习
用循环在终端打印如下图案
```c
*
**
***
****
```
```c
****
***
**
*
```
```c
*
**
***
****
```
```c
****
***
**
*
```
```c
*
***
*****
***
*
```
```c
*
* *
* *
*******
```
```c
A
ABA
ABCBA
ABCDCBA
```
规律:
# 作业
1. 完成测试题
[判断、循环测试题.docx](attachments/WEBRESOURCE1b1c0ef38fb7e7623e35a7ffc254fd87判断、循环测试题.docx)
1. 编程实现一个学习100以内数学四则运算的C语言小程序要求随机生成题目让用户键入答案正确则输出"答对了!你真棒!",错误则提示"答错了,再接再厉"并运行重新回答,每题共三次机会,三次皆未答对则结束程序,答对则进行下一题,若想结束则输入''Esc"。
(提示100以内随机数生成使用rand()%100并添加头文件"#include <stdlib.h>")。