流程控制
流程控制
苏丙榅1. 流程结构概述
程序流程结构是指编程中用于组织和控制代码执行顺序的结构。通过流程结构,可以按照特定的逻辑和条件来控制代码的执行路径,从而实现不同的功能和逻辑控制。以下是常见的程序流程结构:
顺序结构(Sequence Structure)
:按照代码编写顺序从上到下一行接一行地依次执行。1
2
3
4
5
6
7
8
9
10
11
int main()
{
bool flag = true;
flag = !flag;
printf("flag = %d\n", flag);
flag = !flag;
printf("flag = %d\n", flag);
return 0;
}通过上面的示例代码可以看到,顺序结构的逻辑非常简单,下文就不再进行赘述。
选择结构(Selection/Decision Structure)
:根据给定的条件选择性地执行不同的代码块。循环结构(Iteration/Loop Structure)
:循环执行一段代码,直到满足特定的条件为止。跳转结构(Jump Structure)
:用于在代码执行过程中跳转到特定的位置,改变代码执行的流程。
这些程序流程结构可以根据实际需求嵌套和组合使用,以实现复杂的逻辑控制和算法实现。编程语言提供了对应的语法和关键字来支持这些流程结构的使用。具体的语法和用法可能会因编程语言而异,因此在编写代码时应参考相应的语言文档和规范。
2. 选择结构
2.1 if 语句
if语句是一种常见的选择结构,用于根据给定的条件选择性地执行不同的代码块。if语句根据条件的真假来确定执行哪个代码块。
if 语句的一般语法结构如下:
1 | if (condition) |
其中,condition
是一个布尔表达式,当条件为真时,执行大括号{}
内的代码块。如果条件为假,则跳过整个代码块,继续执行后续的代码。
示例程序如下:
1 |
|
布尔表达式age1 > age2
不成立,所以第 8 行的输出是不会执行的。
2.2 if…else 语句
if 语句也可以与 else
结合使用,来处理条件为假时的情况,即执行不同的代码块。下面是if-else
语句的语法示例:
1 | if (condition) |
示例程序如下:
1 |
|
上面的代码要求我们通过键盘输入一个年龄,程序根据我们的输入就能判断这个年龄属于成年人还是未成年人:
1 | // 第一次执行 |
我们在程序中输入了不同的数据,程序对布尔表达式的结果继续了判断,最终执行了不同的代码分支。
2.3 if…else if…else 语句
在C语言中,如果想要进行两个及以上的条件判断,使用if-else
结构是无法满足需求的,此时可使用if-else if-else
,该结构的语法如下:
1 | if (condition1) |
在C语言中,if
和else if
后面的条件表达式用圆括号括起来,并以大括号包围代码块:每个条件之间使用else if
进行连接,else if
的数量可以是 N 个,最后的else
如果不需要可以忽略。
在使用以上语法进行条件判断的时候务必注意一个问题:这些条件语句之间是互斥关系,如果其中一个条件判断为真,就不会再对其他条件进行判断了。
1 | // 版本1 |
在上面的示例程序中接收一个分数输入,然后根据制定的规则对分数进行等级划分,执行的结果如下:
1 | 请输入你考试成绩: |
如果对上面的条件判断稍微做一些手脚,那么得到的结果就完全不一样了:
1 | // 版本2 |
执行程序,输入相同的数据,得到的结果如下:
1 | 请输入你考试成绩: |
在上面两段程序中,使用同样的等级判断标准,同样的分数,但是得到的等级却不一样,原因就在于我们在程序中的判断方式发生了变化,第二段程序的判断逻辑是有问题的。
if...else if...else...if...else
这是一个完整的结构,结构中的所有条件都是互斥的,一个条件为真之后,不会再对其他条件进行判断if
、if...else
、if...else if...else
这是三个独立的判断结构,独立的判断结构之间是不互斥的- 在版本1中,判断结构只有一组,而在版本2中判断结构就变成多组了
- 版本2中会先执行第 15 行代码,再执行第 19 行,发生了数据覆盖
2.4 三目运算符
三目运算符(也称为条件运算符)是一种简洁的条件表达式。它可以在一行代码中根据条件的真假返回不同的值。
一般来说,三目运算符的语法如下:
1 | condition ? expression1 : expression2 |
其中,condition
是一个布尔表达式,如果为真,则返回expression1
的值;如果为假,则返回expression2
的值。
以下是一个示例:
1 |
|
上面代码中通过两种方式对连个整数进行比较,并求出最大值,结果如下:
1 | max = 20 |
由此可见,使用三目运算符能够使程序更加精简,但可读性也会有所降低。
2.5 switch 语句
switch语句是一种多分支选择结构,用于根据不同的条件值选择性地执行不同的代码块。它提供了一种比使用多个if...else if...else
语句更清晰和简洁的方法。
一般来说,switch语句的语法结构如下:
1 | switch (expression) |
在这个结构中,expression
是一个表达式,它的值将与每个case
语句后的value
进行比较。如果expression
的值与某个value
相等,就执行对应的代码块,并在代码块结束后使用break
语句跳出switch
语句。如果没有匹配到任何的case
,就会执行default
后的代码块。
以下是一个示例:
1 |
|
对程序进行测试会得到以下输出:
1 | 请输入数字: |
根据day
的值,选择不同的代码块进行执行。如果day
的值为6,打印出的就是 “周末”。
需要注意的是,如果某个case
的代码块执行完毕后没有使用break
语句,将会继续执行后面的代码块(即”穿透”到下一个case
)。这可以用来处理某些具有共同逻辑的情况,如上述示例中的周末情况。
另外,在C语言中,switch语句的条件有以下几个要求:
条件表达式必须是一个整型值,可以是整数、字符或枚举类型
。在C语言中,浮点数、字符串或其他数据类型不能作为 switch 语句的条件。case后面的值必须是一个常量表达式
,不能使用变量或其他表达式。- 每个 case 语句结束后必须使用
break
语句来跳出整个 switch 语句块,否则将会”穿透”到后续的 case 执行。
3. 循环结构
3.1 for 语句
在C语言中,for
语句是一种循环语句,用于重复执行一段代码块,直到指定的循环条件不再满足。for
语句通常在已知循环次数的情况下使用。
一般来说,for
语句的语法结构如下:
1 | for (initialization; condition; increment/decrement) |
initialization
:在循环开始前执行的初始化代码,通常用于初始化循环变量;condition
:循环条件,只有当条件满足时循环会继续执行;increment/decrement
:在每次循环迭代完成后执行的增量/减量操作,用于更新循环变量的值;
以下是一个示例:
1 |
|
代码输出的信息如下:
1 | 循环变量的值为:1 |
在上述示例中,for
语句将循环变量i
初始化为1,然后检查条件i <= 5
是否满足。如果条件为真,则执行代码块,并在每次循环迭代完成后将i
的值增加1。当i
的值为6时,不再满足条件,循环终止。
for
语句的循环条件可以是任何能够产生布尔值(真或假)的表达式。例如,可以使用比较运算符(如 <
、>
、<=
、>=
、==
、!=
)来判断条件,也可以使用逻辑运算符(如&&
、||
)进行复合条件判断。
需要注意的是,for
循环中的初始化、条件和增量/减量操作都是可选的
。如果省略了初始化或增量/减量操作,可以在循环外部定义和更新循环变量。如果省略了条件,则被认为永远为真,从而变成一个无限循环(死循环)。
在循环体内部,可以使用break
语句跳出循环,提前结束循环的执行,或使用continue
语句跳过当前迭代,继续下一次循环迭代。
for
语句在C语言中经常用于迭代数组、列表和其他数据结构中的元素,以及执行指定次数的重复操作。
3.2 while 语句
在C语言中,while
语句是一种循环语句,用于重复执行一段代码块,直到指定的循环条件不再满足。while
语句通常用于未知循环次数的情况下。
一般来说,while
语句的语法结构如下:
1 | while (condition) |
condition
是循环条件,只有当条件满足时,循环会继续执行对应的代码块。
以下是一个示例:
1 |
|
程序输出的结果如下:
1 | 循环变量的值为:1 |
在上述示例中,while
语句首先检查条件i <= 5
是否满足。如果条件为真,则执行代码块中的语句,并在每次循环迭代完成后将i
的值增加1。当i
的值为6时,不再满足条件,循环终止。
需要注意的是,循环体内的代码块应该包含导致循环条件最终为假的操作,否则会导致无限循环。在循环体内部,可以使用break
语句跳出循环,提前结束循环的执行,或使用continue
语句跳过当前迭代,继续下一次循环迭代。
while
语句适用于任何循环次数未知的情况,例如在读取数据时,可以使用while
语句循环读取,直到满足某个终止条件为止。
3.3 do…while 语句
在C语言中,do...while
语句是一种循环语句,用于至少执行一次代码块,并在每次执行后检查循环条件,如果条件满足,则继续执行循环。与while
语句不同,do...while
语句先执行代码块,再判断条件。
一般来说,do...while
语句的语法结构如下:
1 | do |
condition
是循环条件,当条件满足时,循环会继续执行对应的代码块。在每次执行代码块后,会检查condition
的值。
以下是一个示例:
1 |
|
程序输出的信息如下:
1 | 循环变量的值为:1 |
在上述示例中,do
语句先执行代码块中的语句,然后再进行条件判断,即使条件不满足,也会至少执行一次代码块。condition
的值为真时,继续执行代码块,直到条件为假时,循环终止。
需要注意的是,与while
和for
循环不同,do...while
循环中的代码块至少会执行一次,无论条件是否满足。如果在循环体内使用break
语句提前结束循环,也会在第一次执行后跳出循环。
do...while
语句适用于需要至少执行一次循环体的情况,然后根据条件决定是否继续执行循环。
3.4 嵌套循环
在C语言中,嵌套循环是指在一个循环内部再嵌套一个或多个循环
。通过嵌套循环,可以实现对多维数据结构的遍历、组合问题的解决以及一些复杂的算法。嵌套循环的语法结构如下,此处使用 for 来给大家举例:
1 | for (初始化语句1; 条件表达式1; 增量/减量操作1) |
也可以使用while
或do...while
来实现嵌套循环,只需将相应的语法结构放置在另一个循环体中。
以下是一个示例,展示了一个简单的嵌套循环:
1 |
|
在上述示例中,外层循环执行3次,内层循环每次外层循环执行时都会执行3次。因此,总共会输出9对数字。程序输出的结果如下:
1 | i = 1, j = 1 |
在嵌套循环中,内层循环的每次迭代都会完全执行完毕,然后外层循环再进行下一次迭代。可以根据具体问题的需求,在嵌套循环中进行条件判断、嵌套层级的控制、循环变量的更新等操作。
需要注意的是,嵌套循环的层数过多,循环次数过大可能会导致性能问题,因此在编写嵌套循环时应考虑算法的效率和优化。
关于嵌套循环,不仅仅局限于for
和for
之间的嵌套,for
、while
、do…while
之间都可以相互嵌套或者自我嵌套,大家举一反三,此处不再举例。
4. 跳转结构
在C语言中,跳转结构(Jump Statements)用于控制程序在特定条件下跳转到代码的其他位置。主要有以下几种跳转结构:
break
语句:用于跳出当前循环或switch
语句。continue
语句:用于结束当前迭代,跳到下一次迭代。goto
语句:用于无条件跳转到程序中的指定标记处。
4.1 break
当break
语句被执行时,程序将跳出最内层的循环或switch
语句的执行,并继续执行后续的代码。
1 |
|
- 第 13 行:跳出 while 循环,程序开始执行第 16 行
- 第 27 行:跳出第 21 行的内层 for 循环,程序开始执行第 30 行
- 第 32 行:跳出第 18 行的外层 for 循环,程序开始执行第 35 行
4.2 continue
当continue
语句被执行时,程序将跳过当前迭代中剩余的代码,然后继续下一次迭代。
1 |
|
程序输出的结果为:
1 | sum = 25 |
很显然上面的程序是想求出10以内的奇数之和,即1+3+5+7+9=25
,通过continue
完美跳过了所有的i
为偶数的情况。
4.3 goto
goto
语句是C语言中的一种跳转语句,它允许无条件地将程序控制转移到程序中的指定位置。goto
语句的语法如下:
1 | goto label; |
其中,label
是一个用户定义的标识符,它通常表示要跳转到的位置。标识符通常位于goto
语句之后,并且位于冒号(:
)之前。需要注意以下几点:
label
必须是在当前函数内定义的标签。标签的命名规则与变量的命名规则相同,由字母、数字和下划线组成,但标签不能与C语言的关键字冲突。goto
语句通常用于跳转到同一函数内的某个位置,但也可以跳转到同一文件中的其他函数内的标签(不推荐)。goto
语句应慎用,因为过多或滥用goto
语句可能会导致代码逻辑混乱、难以维护和阅读。通常情况下,可以使用循环或条件语句等结构化的控制流语句来代替goto
语句。
以下是一个简单的示例,展示了goto
语句的用法:
1 |
|
程序输出的结果如下:
1 | 当前的数字是 1 |
在上述示例中,使用goto
语句创建了一个简单的循环,循环打印数字1到5,并在最后输出”结束”。
但请注意,以上程序仅作为示例。通常情况下,可以使用更结构化的控制流语句(例如for
循环或while
循环)来实现类似的功能,不要使用goto,不要使用goto,不要使用goto
。