【重学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 语句则适用于基于一个表达式的离散值来执行多个不同的代码块。在选择使用哪种结构时,应根据具体的应用场景和需求来决定。