LV01-04-C语言-控制语句

本文主要是C语言基础——控制语句相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows windows11
Ubuntu Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
SecureCRT Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日
开发板 正点原子 i.MX6ULL Linux阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
STM32开发板 正点原子战舰V3(STM32F103ZET6)
点击查看本文参考资料
参考方向 参考原文
------
点击查看相关文件下载
--- ---

一、顺序结构

先执行第一条语句,然后是第二条、第三条……一直到最后一条语句,这称为顺序结构。

image-20220125194507922

二、选择结构

1. if…else…

1.1基本形式

1
2
3
4
5
6
7
8
if(表达式)
{
语句块1...; // 表达式为真,执行语句1
}
else
{
语句块2...; // 表达式非真,执行语句2
}
image-20220125195352926

1.2嵌套形式

1
2
3
4
5
6
7
if(表达式)
if(表达式) 语句块1...;
else 语句块2...;
else
if(表达式) 语句块3...;
else 语句块4...;

1.3阶梯形式

1
2
3
4
5
6
if (表达式1) 语句块1...;
else if(表达式2) 语句块2...;
else if(表达式3) 语句块3...;
else if(表达式4) 语句块4...;
...
else 语句块n...;
image-20220125200142589

【注意】

(1)语句块只有单条语句时, { } 可以省略,但是当有若干条语句时,必须用 { } 括起来。

(2)对于表达式,一般情况下为逻辑表达式或关系表达式;也可以是任意类型(包括整型、实型、字符型、指针类型)

(3)要注意表达式中的判断条件原则是非0即为真

(4) if 语句嵌套时, else 总是与它上面的最近的 if 配对,与书写格式无关。要实行强行的配对关系可以利用 { } 来实现。

2. switch

2.1基本形式

1
2
3
4
5
6
7
8
switch(表达式)
{
case 常量表达式1:语句块1...;break;
case 常量表达式2:语句块2...;break;
...
case 常量表达式n:语句块n...;break;
default:语句块n+1;break; /* 放在最后时default后边的break可以省略,其他位置则不可省略 */
}
image-20220125203408073

【注意】

(1)每个常量表达式的值必须各不相同,否则将会出现矛盾。

(2)当表达式的值与 case 后面的常量表达式值(可以是整型、字符型或者枚举型)相等时,就执行此case后面的语句。 case 常量: 只起语句标号的作用。另外要注意多个 case 可以执行一组语句

(3) switch 中的表达式可以是整型、字符型或枚举型

(4) break 语句用于强行跳出 switch ,一般每个 case 后面应有一个 break 语句, default 分支后的 break 可以省略。一般情况 default 分支都放在最后面,当然,也可以放在开头或者中间,但是此时的 break 就不可以省略了。

(5)语句块是可以使用花括号 { } 包裹起来的,但是大多数情况似乎都不使用花括号。

2.2可以定义变量嘛?

为什么会有这一部分笔记呢?因为踩坑了呗,先看一个实例吧:

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

/* 主函数 */
int main(int argc, char *argv[])
{
int n = 1;
switch(n)
{
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("default\n");
break;
}

return 0;
}

然后我们编译上边的程序,这个时候是不会有任何问题的,但是要是我们想在分支定义一个局部变量怎么办?我们来试一下:

点击查看详情
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

/* 主函数 */
int main(int argc, char *argv[])
{
int n = 1;
switch(n)
{
case 1:
printf("1\n");
break;
case 2:
int a = 10;
printf("2 a=%d\n", a);
break;
default:
printf("default\n");
break;
}

return 0;
}

这个时候我们再来编译一下:

1
2
3
4
5
hk@vm:~/6temp/test$ gcc test.c -Wall
test.c: In function ‘main’:
test.c:13:4: error: a label can only be part of a statement and a declaration is not a statement
int a = 10;
^

我们发现,居然报错了,原因上边其实已经提示了,在c语言中想要在switch语句的某一个分支中定义变量,我们需要加上为这分支加上花括号。将上边报错的分支修改为如下的形式(花括号也可将break包裹在内):

1
2
3
4
5
6
case 2:
{
int a = 10;
printf("2 a=%d\n", a);
}
break;

2.3多个值?

有这样的情况怎么办,有0 1 2三个匹配对象执行相同的语句,switch也是支持的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

/* 主函数 */
int main(int argc, char *argv[])
{
int n = 2;
switch (n)
{
case 1:
case 2:
printf("2\n");
break;
default:
printf("default\n");
break;
}

return 0;
}

这样 n 是 1 或者 2 的时候都会执行分支2中的语句啦。

三、循环结构

1. while

1.1基本形式

1
2
3
4
while(表达式)
{
语句块...;
}

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

image-20220125205217591

1.2实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main(int argc, char *argv[])
{
int n = 5;
int count = 0;
printf("------cycle start------\n");
while(n > 2)
{
printf("Before statement execution: count=%d, n=%d\n", count, n);
n--;
count++;
printf("After statement execution: count=%d, n=%d\n", count, n);
}
printf("------cycle end------\n");
printf("count = %d, n = %d \n", count, n);
return 0;
}
image-20220125205922983

【注意】 while 循环是先判断表达式为真,然后才执行循环,若为假,则直接结束循环,不会再执行循环体内的语句块。

2. do…while

2.1基本形式

1
2
3
do{
语句块...;
}while(表达式);

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

image-20220125210700859

2.2实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main(int argc, char *argv[])
{
int n = 5;
int count = 0;
printf("------cycle start------\n");
do{
printf("Before statement execution: count=%d, n=%d\n", count, n);
n--;
count++;
printf("After statement execution: count=%d, n=%d\n", count, n);
}while(n > 5);
printf("------cycle end------\n");
printf("count = %d, n = %d \n", count, n);

return 0;
}
image-20220125211932332

【注意】 do…while 循环是先执行一次循环,然后才判断表达式为真,然后才继续执行循环,若为假,则直接结束循环,不会再执行循环体内的语句块。所以当两个实例中的判断条件 n > 2 变为 n > 5 时 while 循环结构一次也不执行,而 do…while 循环结构会执行一次,这点需要注意。

3. for

3.1基本形式

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

执行过程:

(1) 先执行“表达式1”。

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

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

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

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

image-20220126111212925

【注意】

(1)“表达式1”仅在第一次循环时执行,以后都不会再执行,可以认为这是一个初始化语句。“表达式1”可省略,但循环之前应给循环变量赋值

(2)表达式2”一般是一个关系表达式,决定了是否还要继续下次循环,称为“循环条件”。“表达式2”可省略,将陷入死循环

(3)“表达式3”很多情况下是一个带有自增或自减操作的表达式,以使循环条件逐渐变得“不成立”。“表达式3”可省略,但在循环体中增加使循环变量值改变的语句

四、辅助控制语句

1. return

1.1基本形式

1
return (表达式); /* 有没有 ( ) 都可以*/

1.2基本应用

  • 返回函数的值

当 return 应用在函数中时,可以用于返回一个值,如 return (10 + 9);

  • 结束程序

当 return 应用在函数中时,不仅可以用于返回一个值,还可以直接结束该函数, return 语句执行完毕,它后边的所有语句不再执行,直接跳到主函数继续执行,若是用在主函数中,则遇到 return 直接结束主函数,整个程序结束,后边的语句不再执行。

【注意】 return 语句可以有多个,可以出现在函数体的任意位置,但是每次调用函数只能有一个 return 语句被执行,所以只有一个返回值(少数的编程语言支持多个返回值,例如 Go 语言)。

2. goto

goto 语句是一种无条件流程跳转语句,通常 goto 语句与 if 语句结合使用,当满足一定条件时,程序流程跳转到指定标号处,接着往下执行。

2.1基本形式

1
2
3
4
5
6
/* 定义一个语句标识 flag_name (flag_name只是一个名字)*/
flag_name : /* 语句标识后的冒号不能省略 */
语句块...;

/* goto 语句的调用 */
goto flag_name; /* 程序将从对应 flag_name 的代码处开始往下执行。 */

【注意】 flag_name 后边的语句可以加 { } ,也可以不加。不过加上的话可读性会强一些。

2.2基本应用

  • 跳出循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
int main(int argc, char *argv[])
{
int count = 0;
flag:
{
printf("------goto statement execution------\n");
printf("------cycle end------\n");
printf("count = %d\n", count);
if (count == 3)
return 0;
}
printf("------while cycle start------\n");
while(1)
{
printf("Before statement execution: count=%d\n", count);
count++;
printf("After statement execution: count=%d\n", count);
if(count > 3)
goto flag;
}
return 0;
}
image-20220126133428798

goto flag_name; 语句放在循环中用于跳出循环,用于结束循环时,此时 flag_name 处的代码有两种情况:

(1)第一种是放在循环上边,比循环先执行,这个时候, flag_name 处的程序会先执行一遍,所以,切记,这里边不要直接放 return 语句,否则程序直接结束了,有需要的话可以加一个判断,以保证程序可以正常运行。

(2)第二种是放在循环下边,这个时候,只有满足了跳转指令时,程序才会跳转到 flag_name 处执行。

  • 构成循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 1;
int sum=0;
flag:
if(i <= 5)
{
sum = sum + i;
i++;
goto flag;
}
printf("%d\n",sum);
return 0;
}

3. break

3.1基本形式

1
break;

break 语句通常用在循环语句和开关语句中。当 break 用于开关语句 switch 中时,可使程序跳出 switch 而执行 switch 以后的语句;如果没有 break 语句,则将成为一个死循环而无法退出。

当 break 语句用于 do-while、for、while 循环语句中时,可使程序终止循环而执行循环后面的语句,通常 break 语句总是与 if 语句联在一起,即满足条件时便跳出循环。

3.2基本应用

  • 跳出一层循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
int main(int argc, char *argv[])
{
int n,i;
printf("自数1~100全部素数:\n");
for(n = 2; n <= 100; n++)
{
for(i = 2; i < n; i++)
{
if (n % i == 0)
break;
}
if(i >= n)
printf("%d\t",n);
}
printf("\n");
return 0;
}
image-20220126134630921

【注意】

(1) break 语句对 if-else 的条件语句不起作用;

(2)在多层循环中,一个 break 语句只向外跳一层。

4. continue

4.1基本形式

1
continue;

continue 语句的作用是跳过循环体中剩余的语句而强行执行下一次循环。 continue 语句只用在 for、while、do-while 等循环体中,常与 if 条件语句一起使用,用来加速循环

4.2基本应用

  • 直接跳过剩余语句执行下一次循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main(int argc, char *argv[])
{
int n;
for(n = 1; n <= 30; n++)
{
if(n % 2 == 0)
continue;
printf("%d\t", n);
}
printf("\n");
return 0;
}

image-20220126140539529