【重学C语言】五、分支结构
- 三种结构
- 分支结构
- `if` 语句
- 示例 1:基本的 if 语句
- `if...else` 语句
- 示例 2:if...else 语句
- 嵌套 `if`
- 示例 3:嵌套的 if 语句
- `if` 语句与逻辑运算符
- 示例 4:使用逻辑与(&&)
- 示例 5:使用逻辑或(||)
- 示例 6:使用逻辑非(!)
- 示例 7:组合使用逻辑运算符
- `if` 语句与关系运算符
- 示例 8:比较两个整数
- 示例 9:检查字符串是否相等
- 示例 10:检查变量是否在特定范围内
- 示例 11:检查用户输入
- `if ... else` 注意事项
- `switch` 语句
- 示例 12:使用 `switch` 语句
- `switch` 注意事项
- `if` 和 `switch` 语句的应用
- `if` 语句的应用
- `switch` 语句的应用
三种结构
C语言中的三种基本结构是指顺序结构、选择结构(分支结构)和循环结构。这三种结构是构成C语言程序的基本框架,它们能够组合起来实现复杂的逻辑和算法。
- 顺序结构:
顺序结构是程序中最基本的结构,它按照代码的顺序逐行执行。在顺序结构中,语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构。
例如:
#include <stdio.h>int main() {printf("Hello, ");printf("World!\n");return 0;
}
上面的程序就是按照顺序结构执行的,先输出"Hello, “,然后输出"World!”。
- 选择结构(分支结构):
选择结构是根据条件判断的结果来选择执行不同的代码块。C语言提供了if
、if...else
、switch
等关键字来实现选择结构。
例如,使用if...else
实现的选择结构:
#include <stdio.h>int main() {int num = 5;if (num > 0) {printf("Number is positive.\n");} else {printf("Number is non-positive.\n");}return 0;
}
- 循环结构:
循环结构是指程序中需要反复执行某段代码的结构。C语言提供了for
、while
、do...while
等关键字来实现循环结构。
例如,使用for
循环打印1到5的整数:
#include <stdio.h>int main() {for (int i = 1; i <= 5; i++) {printf("%d\n", i);}return 0;
}
这三种结构可以单独使用,也可以组合起来使用,以构建更复杂的程序逻辑。在实际的编程中,程序员会根据需要灵活运用这三种结构来实现特定的功能。
分支结构
分支结构(也称为选择结构或条件结构)是程序设计中用于根据特定条件选择不同的执行路径的一种结构。在C语言中,分支结构主要由if
语句、if...else
语句、switch
语句等来实现。
if
语句
if
语句用于在满足某个条件时执行一段代码。其基本语法如下:
if (condition) {// 代码块,当 condition 为真时执行
}
如果 condition
为真(非零),则执行 if
语句后面的代码块。
示例 1:基本的 if 语句
#include <stdio.h>int main() {int a = 5;if (a > 0) {printf("a is positive.\n");}return 0;
}
在这个例子中,我们检查变量 a
是否大于 0。如果是,就打印出 “a is positive.”。
if...else
语句
if...else
语句用于在满足某个条件时执行一段代码,否则执行另一段代码。其基本语法如下:
if (condition) {// 当 condition 为真时执行的代码块
} else {// 当 condition 为假时执行的代码块
}
示例 2:if…else 语句
#include <stdio.h>int main() {int b = -3;if (b > 0) {printf("b is positive.\n");} else {printf("b is non-positive.\n");}return 0;
}
在这个例子中,我们检查变量 b
是否大于 0。如果是,我们打印 “b is positive.”;如果不是(即 b
小于或等于 0),我们打印 “b is non-positive.”。
嵌套 if
嵌套 if
语句是 if
语句的一种扩展形式,其中 if
语句或 if...else
语句可以作为另一个 if
或 if...else
语句的一部分。这种结构允许我们在一个条件的基础上进一步细分决策流程,根据多个条件执行不同的代码块。
嵌套 if
语句的基本语法如下:
if (condition1) {// 当 condition1 为真时执行的代码块if (condition2) {// 当 condition1 和 condition2 都为真时执行的代码块} else {// 当 condition1 为真但 condition2 为假时执行的代码块}
} else {// 当 condition1 为假时执行的代码块
}
在这个例子中,condition2
的检查仅在 condition1
为真时执行。如果 condition1
为假,那么不会检查 condition2
,而是直接执行与 else
关联的代码块。
嵌套 if
语句可以多层嵌套,每一层都根据前一个 if
语句的结果来决定是否执行。然而,过度使用嵌套 if
语句可能导致代码难以理解和维护。因此,在编写嵌套 if
语句时,最好保持结构清晰,并使用适当的缩进和注释来增强代码的可读性。
示例 3:嵌套的 if 语句
#include <stdio.h>int main() {int c = 10;int d = 5;if (c > 5) {printf("c is greater than 5.\n");if (d < 10) {printf("And d is less than 10.\n");}}return 0;
}
在这个例子中,我们首先检查变量 c
是否大于 5。如果是,我们打印 “c is greater than 5.”,然后进一步检查变量 d
是否小于 10。如果 d
也满足条件,我们打印 “And d is less than 10.”。
if
语句与逻辑运算符
在 C 语言中,if
语句经常与逻辑运算符一起使用,以便根据多个条件的组合来执行不同的代码块。逻辑运算符包括 &&
(逻辑与)、||
(逻辑或)和 !
(逻辑非)。这些运算符可以帮助我们构建更复杂的条件表达式。
下面是一些使用 if
语句和逻辑运算符的 C 语言实例:
示例 4:使用逻辑与(&&)
#include <stdio.h>int main() {int a = 5;int b = 10;if (a > 0 && b > 0) {printf("Both a and b are positive.\n");} else {printf("Either a or b is not positive.\n");}return 0;
}
在这个例子中,只有当 a
和 b
都大于 0 时,才会执行 if
语句块中的代码。
示例 5:使用逻辑或(||)
#include <stdio.h>int main() {int x = -5;int y = 15;if (x > 0 || y > 0) {printf("At least one of x or y is positive.\n");} else {printf("Both x and y are non-positive.\n");}return 0;
}
在这个例子中,只要 x
或 y
中至少有一个大于 0,就会执行 if
语句块中的代码。
示例 6:使用逻辑非(!)
#include <stdio.h>int main() {int z = 0;if (!z) {printf("z is zero or false.\n");} else {printf("z is non-zero or true.\n");}return 0;
}
在这个例子中,!z
表示对 z
的逻辑非操作。因为 z
是 0(在 C 语言中,0 通常被视为假),所以 !z
的结果是真,因此会执行 if
语句块中的代码。
示例 7:组合使用逻辑运算符
#include <stdio.h>int main() {int m = 3;int n = 4;int o = 2;if ((m > 0 && n > 0) || o > 5) {printf("Either both m and n are positive, or o is greater than 5.\n");} else {printf("Neither both m and n are positive, nor o is greater than 5.\n");}return 0;
}
在这个例子中,我们组合使用了逻辑与和逻辑或。只有当 m
和 n
都大于 0,或者 o
大于 5 时,才会执行 if
语句块中的代码。
逻辑运算符允许我们构建复杂且灵活的条件表达式,从而根据多个条件的组合来控制程序的流程。在实际编程中,根据具体的需求,我们可以使用这些逻辑运算符来创建精确的条件判断。
if
语句与关系运算符
在C语言中,if
语句经常与关系运算符一起使用,以根据两个或多个值之间的关系来决定执行哪一段代码。关系运算符用于比较两个操作数,并返回一个布尔值(真或假)。常见的关系运算符包括:==
(等于)、!=
(不等于)、>
(大于)、<
(小于)、>=
(大于或等于)和<=
(小于或等于)。
下面是一些使用if
语句和关系运算符的C语言实例:
示例 8:比较两个整数
#include <stdio.h>int main() {int a = 10;int b = 20;if (a < b) {printf("a is less than b.\n");} else {printf("a is not less than b.\n");}return 0;
}
在这个例子中,我们比较了两个整数a
和b
。如果a
小于b
,则执行if
语句块中的代码。
示例 9:检查字符串是否相等
#include <stdio.h>
#include <string.h>int main() {char str1[] = "Hello";char str2[] = "World";if (strcmp(str1, str2) != 0) {printf("str1 is not equal to str2.\n");} else {printf("str1 is equal to str2.\n");}return 0;
}
在这个例子中,我们使用strcmp
函数来比较两个字符串str1
和str2
。如果它们不相等,strcmp
会返回一个非零值,因此if
语句的条件为真。
示例 10:检查变量是否在特定范围内
#include <stdio.h>int main() {int x = 5;if (x >= 0 && x <= 10) {printf("x is within the range of 0 to 10.\n");} else {printf("x is not within the range of 0 to 10.\n");}return 0;
}
在这个例子中,我们检查变量x
是否在0到10的范围内。我们使用了逻辑与运算符&&
来组合两个关系表达式。
示例 11:检查用户输入
#include <stdio.h>int main() {int age;printf("Enter your age: ");scanf("%d", &age);if (age >= 18) {printf("You are an adult.\n");} else {printf("You are not an adult.\n");}return 0;
}
在这个例子中,程序会提示用户输入年龄,并使用if
语句和关系运算符来判断用户是否是成年人。
通过结合if
语句和关系运算符,我们可以编写出能够根据特定条件执行不同操作的灵活程序。这种条件判断在编程中非常常见,特别是在需要根据用户输入或程序状态做出决策的情况下。
if ... else
注意事项
在使用 if ... else
语句时,有几个关键的注意事项需要牢记,以确保代码的正确性和可读性。以下是使用 if ... else
语句时的一些重要提示:
-
条件表达式的结果:
if
语句后面的条件表达式必须返回一个布尔值(即true
或false
)。在 C 语言中,任何非零值通常被视为true
,而零值被视为false
。但是,为了代码清晰,最好直接使用布尔表达式或比较运算的结果。 -
代码块:
if
和else
语句后面的代码块必须用花括号{}
括起来,即使代码块只包含一条语句。这是一个良好的编程习惯,因为它可以提高代码的可读性,并避免潜在的错误。 -
嵌套使用:
if ... else
语句可以嵌套使用,以处理更复杂的条件逻辑。但是,过度嵌套会使代码难以理解和维护。因此,应尽量避免深度嵌套,并考虑使用其他结构(如函数或switch
语句)来简化逻辑。 -
可读性:
为了提高代码的可读性,建议将条件表达式和if ... else
语句块放在合适的缩进级别,并使用有意义的变量名和注释来解释复杂的逻辑。 -
避免空语句:
不要在if
或else
后面直接跟分号(;
),这会导致一个空语句被执行。这通常是一个错误,应该避免。 -
逻辑运算符的使用:
在条件表达式中,可以使用逻辑运算符(如&&
、||
和!
)来组合多个条件。但是,要注意逻辑运算符的优先级和结合性,必要时使用括号来明确优先级。 -
else if
的使用:
如果需要检查多个条件,并为每个条件执行不同的代码块,可以使用else if
。这可以避免深度嵌套的if
语句,并使代码更加清晰。 -
避免魔法数字:
在条件表达式中,避免直接使用硬编码的数字(称为“魔法数字”)。相反,应将这些数字定义为常量或变量,并为其赋予有意义的名称。 -
错误处理:
当使用if ... else
语句进行条件判断时,不要忘记考虑可能出现的错误情况,并为其编写适当的错误处理代码。 -
测试与调试:
编写完包含if ... else
语句的代码后,务必进行充分的测试和调试,以确保其按预期工作。特别要注意边界条件和异常情况。
遵循这些注意事项可以帮助你编写出健壮、可维护和易于理解的 if ... else
语句。
switch
语句
switch
语句用于基于不同的情况值来执行不同的代码块。其基本语法如下:
switch (variable) {case value1:// 当 variable 等于 value1 时执行的代码块break;case value2:// 当 variable 等于 value2 时执行的代码块break;// 可以有更多的 casedefault:// 当 variable 不等于任何 case 值时执行的代码块break;
}
在 switch
语句中,break
关键字用于终止 switch
语句的执行,跳出当前的 case
分支。如果没有 break
,程序会继续执行下一个 case
分支,直到遇到 break
或者 switch
语句结束。
当然,下面是一个使用 switch
语句的 C 语言实例。switch
语句允许我们根据一个表达式的值来执行多个代码块中的一个。
示例 12:使用 switch
语句
#include <stdio.h>int main() {int day = 3; // 假设这是从用户输入或其他计算中得到的值switch (day) {case 1:printf("Monday\n");break;case 2:printf("Tuesday\n");break;case 3:printf("Wednesday\n");break;case 4:printf("Thursday\n");break;case 5:printf("Friday\n");break;case 6:printf("Saturday\n");break;case 7:printf("Sunday\n");break;default:printf("Invalid day\n");}return 0;
}
在这个例子中,我们根据变量 day
的值打印出相应的星期几。每个 case
标签后面跟着一个要匹配的值,如果 switch
表达式的结果与某个 case
标签匹配,就会执行那个 case
下的代码,直到遇到 break
语句或者 switch
语句的结束。如果没有 break
语句,程序会继续执行下一个 case
的代码,这通常被称为“case 穿透”(fall-through)。
default
标签是可选的,用于处理所有其他情况,即当 switch
表达式的值没有与任何 case
标签匹配时。在这个例子中,如果 day
的值不是 1 到 7 之间的任何一个数,就会执行 default
下的代码,打印 “Invalid day”。
注意:在实际编程中,为了代码的可读性和维护性,通常建议为每个 case
使用 break
语句,除非你确实需要利用 case 穿透的特性。
switch
注意事项
在使用 switch
语句时,有几点关键的注意事项需要牢记,以确保代码的正确性和可读性。以下是使用 switch
语句时的一些重要提示:
-
case穿透:
每个case
后面都应该加上break;
语句,以跳出switch
语句。如果没有break
语句,程序会继续执行下一个case
中的代码块,这种情况称为“case穿透”,可能会导致逻辑错误或意外结果。为了避免这种情况,务必在每个case
结尾添加break
语句,除非有意使多个case
执行相同的代码。 -
case中的变量定义:
在C89标准中,不允许在case
中定义变量。但在C99标准中,这是允许的。不过,为了避免代码的可读性和维护性问题,建议在switch
语句之前定义所有需要使用的变量。 -
不支持浮点数和字符串:
switch
语句在C语言中只支持整型和字符型表达式,不支持浮点数或字符串类型。如果需要基于浮点数或字符串进行判断,应使用if-else
语句或其他方法。 -
default分支:
即使程序不需要处理默认情况,也建议包含一个default
分支,并在其中至少包含break;
语句。这样做可以防止其他开发者误以为遗漏了default
处理,并提供一个明确的代码结构。 -
代码块的使用:
不管case
分支中有多少条语句,都建议使用花括号{}
将其括起来。这可以提高代码的可读性,并避免潜在的逻辑错误。 -
case值的唯一性:
虽然C语言不强制要求case
的值唯一,但为了确保逻辑清晰,最好确保每个case
的值都是唯一的。如果多个case
有相同的值,它们将执行相同的代码块,这可能会导致逻辑上的混淆。 -
避免过多的case:
虽然switch
语句支持大量的case
分支,但过多的case
会使代码难以理解和维护。如果逻辑变得过于复杂,考虑使用其他结构(如查找表或函数指针数组)来简化代码。 -
测试与调试:
编写完包含switch
语句的代码后,务必进行充分的测试和调试,以确保其按预期工作。特别要注意边界条件和异常情况。 -
case
和后面的常量一定要有空格
遵循这些注意事项可以帮助你编写出健壮、可维护和易于理解的 switch
语句。
if
和 switch
语句的应用
if
和 switch
语句在编程中都是用于基于特定条件执行不同代码块的控制结构。它们各自有不同的应用场景和优势,下面将详细讨论它们的应用:
if
语句的应用
if
语句主要用于根据一个或多个条件的评估结果来执行相应的代码块。其应用非常广泛,包括但不限于以下几种情况:
- 输入验证:检查用户输入是否满足特定条件,如是否为空、是否在有效范围内等。
if (input != NULL && input_length > 0 && input_length < MAX_LENGTH) {// 处理有效输入
} else {// 处理无效输入或错误
}
- 状态判断:根据对象的当前状态执行不同的操作,如判断一个游戏角色是否活着。
if (character.is_alive) {// 角色活着,执行相应操作
} else {// 角色死亡,执行不同操作
}
- 数值比较:比较两个数值的大小,根据比较结果执行不同操作。
int a = 10;
int b = 20;if (a < b) {printf("a is less than b.\n");
} else {printf("a is not less than b.\n");
}
- 复杂逻辑判断:组合多个条件使用逻辑运算符(如
&&
、||
)进行复杂逻辑判断。
if ((age >= 18 && age <= 65) && is_citizen) {// 成年人且是公民,执行某些操作
} else {// 不满足条件,执行其他操作
}
switch
语句的应用
switch
语句通常用于根据一个表达式的值来执行多个不同的代码块。它适用于有多个离散选项的情况,如菜单选择、状态机或对不同枚举值进行处理。
- 菜单系统:根据用户的选择执行不同的操作。
int choice = get_user_choice(); // 假设这个函数返回用户的选择(1, 2, 3 等)switch (choice) {case 1:// 执行选项 1 的操作break;case 2:// 执行选项 2 的操作break;case 3:// 执行选项 3 的操作break;default:// 处理无效选择break;
}
- 状态机:根据对象或系统的当前状态执行不同的行为。
enum State { IDLE, RUNNING, STOPPED };
enum State currentState = get_current_state();switch (currentState) {case IDLE:// 处理空闲状态break;case RUNNING:// 处理运行状态break;case STOPPED:// 处理停止状态break;default:// 处理未知状态break;
}
- 枚举值处理:对枚举类型的值进行不同处理。
enum Color { RED, GREEN, BLUE };
enum Color myColor = get_color();switch (myColor) {case RED:// 处理红色break;case GREEN:// 处理绿色break;case BLUE:// 处理蓝色break;default:// 处理未知颜色break;
}
总结来说,if
语句适用于根据一个或多个条件的评估结果来执行不同的代码块,而 switch
语句则适用于基于一个表达式的离散值来执行多个不同的代码块。在选择使用哪种结构时,应根据具体的应用场景和需求来决定。