前置知识: C

控制流

00:00
6 min Intermediate

条件判断、循环结构及其控制语句。

1. 条件判断 (Selection)

1.1 if-else 结构

1.1.1 基本用法

if-else 结构是最基本的条件控制语句,用于根据条件执行不同的代码块。

 #include <stdio.h>
 int main() {
  int score = 85;
  if (score >= 90) {
  printf("Excellent\n");
  } else if (score >= 80) {
  printf("Very Good\n");
  } else if (score >= 60) {
  printf("Pass\n");
  } else {
  printf("Fail\n");
  }
  return 0;
 }

1.1.2 嵌套 if-else

 #include <stdio.h>
 int main() {
  int age = 18;
  int has_license = 1;
  if (age >= 18) {
  if (has_license) {
  printf("You can drive\n");
  } else {
  printf("You need a license to drive\n");
  }
  } else {
  printf("You are too young to drive\n");
  }
  return 0;
 }

1.1.3 条件表达式的简写

 #include <stdio.h>
 int main() {
  int a = 10, b = 20;
  // 简单的条件判断可以使用三目运算符
  int max = (a > b) ? a : b;
  printf("Max: %d\n", max);
  // 条件表达式作为函数参数
  printf("Result: %s\n", (a > b) ? "a is larger" : "b is larger");
  return 0;
 }

1.2 switch-case 结构

1.2.1 基本用法

switch-case 结构用于多分支选择,比嵌套的 if-else 更清晰。

 #include <stdio.h>
 int main() {
  char grade = 'B';
  switch (grade) {
  case 'A':
  printf("Great!\n");
  break;
  case 'B':
  printf("Good!\n");
  break;
  case 'C':
  printf("Average\n");
  break;
  case 'D':
  printf("Below Average\n");
  break;
  case 'F':
  printf("Fail\n");
  break;
  default:
  printf("Unknown grade\n");
  }
  return 0;
 }

1.2.2 整数类型的 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:
  case 7:
  printf("Weekend\n");
  break;
  default:
  printf("Invalid day\n");
  }
  return 0;
 }

1.2.3 switch 中的穿透现象

case 语句后没有 break 时,会发生穿透现象,继续执行下一个 case

 #include <stdio.h>
 int main() {
  int month = 2;
  int days;
  switch (month) {
  case 1:
  case 3:
  case 5:
  case 7:
  case 8:
  case 10:
  case 12:
  days = 31;
  break;
  case 4:
  case 6:
  case 9:
  case 11:
  days = 30;
  break;
  case 2:
  days = 28; // 简化处理,未考虑闰年
  break;
  default:
  days = 0;
  printf("Invalid month\n");
  }
  if (days > 0) {
  printf("Month %d has %d days\n", month, days);
  }
  return 0;
 }

2. 循环结构 (Iteration)

2.1 for 循环

2.1.1 基本用法

for 循环常用于已知循环次数的场景,结构清晰。

 #include <stdio.h>
 int main() {
  // 基本 for 循环
  for (int i = 0; i < 10; i++) {
  printf("%d ", i);
  }
  printf("\n");
  // 循环变量初始化、条件、增量都可以省略
  int j = 0;
  for (; j < 10;) {
  printf("%d ", j);
  j++;
  }
  printf("\n");
  return 0;
 }

2.1.2 嵌套 for 循环

 #include <stdio.h>
 int main() {
  // 打印乘法表
  for (int i = 1; i <= 9; i++) {
  for (int j = 1; j <= i; j++) {
  printf("%d*%d=%d\t", j, i, i*j);
  }
  printf("\n");
  }
  return 0;
 }

2.1.3 特殊的 for 循环用法

 #include <stdio.h>
 int main() {
  // 使用多个循环变量
  for (int i = 0, j = 10; i < j; i++, j--) {
  printf("i=%d, j=%d\n", i, j);
  }
  // 无限循环
  // for (;;) {
  // // 循环体
  // }
  return 0;
 }

2.2 while 循环

2.2.1 基本用法

while 循环适用于循环次数不确定的场景,只要条件为真就继续执行。

 #include <stdio.h>
 int main() {
  int i = 0;
  while (i < 10) {
  printf("%d ", i);
  i++;
  }
  printf("\n");
  return 0;
 }

2.2.2 输入验证

 #include <stdio.h>
 int main() {
  int age;
  printf("Enter your age: ");
  // 验证输入是否为有效年龄
  while (1) {
  scanf("%d", &age);
  if (age >= 0 && age <= 120) {
  break;
  }
  printf("Invalid age. Please enter again: ");
  }
  printf("Your age is %d\n", age);
  return 0;
 }

2.2.3 无限循环

 #include <stdio.h>
 int main() {
  int count = 0;
  // 无限循环,直到满足条件跳出
  while (1) {
  printf("Count: %d\n", count);
  count++;
  if (count >= 5) {
  break;
  }
  }
  return 0;
 }

2.3 do-while 循环

2.3.1 基本用法

do-while 循环保证循环体至少执行一次,适用于需要先执行后判断的场景。

 #include <stdio.h>
 int main() {
  int i = 10;
  do {
  printf("Execute once\n");
  i--;
  } while (i < 5);
  return 0;
 }

2.3.2 菜单驱动程序

 #include <stdio.h>
 int main() {
  int choice;
  do {
  printf("\nMenu:\n");
  printf("1. Option 1\n");
  printf("2. Option 2\n");
  printf("3. Exit\n");
  printf("Enter your choice: ");
  scanf("%d", &choice);
  switch (choice) {
  case 1:
  printf("You selected Option 1\n");
  break;
  case 2:
  printf("You selected Option 2\n");
  break;
  case 3:
  printf("Exiting...\n");
  break;
  default:
  printf("Invalid choice\n");
  }
  } while (choice != 3);
  return 0;
 }

3. 循环控制语句 (Control Statements)

3.1 break 语句

3.1.1 基本用法

break 语句用于立即退出当前循环,不再执行循环体中剩余的语句。

 #include <stdio.h>
 int main() {
  for (int i = 0; i < 10; i++) {
  if (i == 5) {
  break; // 当 i 等于 5 时退出循环
  }
  printf("%d ", i);
  }
  printf("\nLoop exited\n");
  return 0;
 }

3.1.2 跳出嵌套循环

 #include <stdio.h>
 int main() {
  for (int i = 0; i < 5; i++) {
  for (int j = 0; j < 5; j++) {
  printf("i=%d, j=%d\n", i, j);
  if (i == 2 && j == 2) {
  goto exit_loop; // 使用 goto 跳出多层循环
  }
  }
  }
  exit_loop:
  printf("Exited nested loops\n");
  return 0;
 }

3.2 continue 语句

3.2.1 基本用法

continue 语句用于跳过本次循环的剩余部分,直接进入下一次迭代。

 #include <stdio.h>
 int main() {
  for (int i = 0; i < 10; i++) {
  if (i % 2 == 0) {
  continue; // 跳过偶数
  }
  printf("%d ", i);
  }
  printf("\n");
  return 0;
 }

3.2.2 跳过特定条件

 #include <stdio.h>
 int main() {
  int numbers[] = {1, 2, 3, 0, 4, 5, 0, 6};
  int size = sizeof(numbers) / sizeof(numbers[0]);
  for (int i = 0; i < size; i++) {
  if (numbers[i] == 0) {
  printf("Skipping zero\n");
  continue;
  }
  printf("Number: %d\n", numbers[i]);
  }
  return 0;
 }

3.3 goto 语句

3.3.1 基本用法

goto 语句用于无条件跳转到指定的标签位置,一般不推荐使用,但在某些场景下可以简化代码。

 #include <stdio.h>
 int main() {
  int i = 0;
  start:
  printf("i = %d\n", i);
  i++;
  if (i < 5) {
  goto start;
  }
  printf("Loop completed\n");
  return 0;
 }

3.3.2 跳过多层循环

 #include <stdio.h>
 int main() {
  for (int i = 0; i < 3; i++) {
  for (int j = 0; j < 3; j++) {
  for (int k = 0; k < 3; k++) {
  printf("i=%d, j=%d, k=%d\n", i, j, k);
  if (i == 1 && j == 1 && k == 1) {
  goto end_of_loops;
  }
  }
  }
  }
  end_of_loops:
  printf("Exited all loops\n");
  return 0;
 }

3.3.3 错误处理

 #include <stdio.h>
 #include <stdlib.h>
 int main() {
  FILE *file;
  file = fopen("nonexistent.txt", "r");
  if (file == NULL) {
  perror("Error opening file");
  goto cleanup;
  }
  // 处理文件...
  fclose(file);
  cleanup:
  printf("Program completed\n");
  return 0;
 }

4. 控制流的最佳实践

4.1 代码风格建议

  • 缩进一致: 使用 4 空格或 1 制表符的缩进
  • 大括号使用: 始终使用大括号包围循环体和条件块
  • 命名规范: 使用有意义的变量名
  • 注释: 为复杂的条件和循环添加注释
  • 换行: 在适当的地方换行,保持代码可读性

4.2 性能优化建议

  • 循环不变量外提: 将循环中不变的计算移到循环外
  • 减少循环内操作: 尽量减少循环体内的计算量
  • 选择合适的循环类型: 根据具体场景选择 forwhiledo-while
  • 避免死循环: 确保循环条件最终能为假
  • 使用 breakcontinue: 合理使用这些语句提高循环效率

4.3 常见错误避免

  • 无限循环: 确保循环条件有终止的可能
  • 嵌套过深: 避免超过 3 层的嵌套,考虑重构为函数
  • 条件判断错误: 注意运算符优先级和逻辑关系
  • 边界条件: 处理好循环的边界情况
  • 变量作用: 合理控制变量的作用域

4.4 最佳实践示例

 #include <stdio.h>
 // 计算斐波那契数列
 void fibonacci(int n) {
  if (n <= 0) {
  printf("Invalid input\n");
  return;
  }
  int a = 0, b = 1;
  printf("Fibonacci sequence: ");
  for (int i = 0; i < n; i++) {
  printf("%d ", a);
  int next = a + b;
  a = b;
  b = next;
  }
  printf("\n");
 }
 // 查找数组中的元素
 int find_element(int arr[], int size, int target) {
  for (int i = 0; i < size; i++) {
  if (arr[i] == target) {
  return i; // 找到元素,返回索引
  }
  }
  return -1; // 未找到元素
 }
 int main() {
  // 调用斐波那契函数
  fibonacci(10);
  // 测试查找函数
  int numbers[] = {10, 20, 30, 40, 50};
  int size = sizeof(numbers) / sizeof(numbers[0]);
  int target = 30;
  int index = find_element(numbers, size, target);
  if (index != -1) {
  printf("Element %d found at index %d\n", target, index);
  } else {
  printf("Element %d not found\n", target);
  }
  return 0;
 }

5. 常见问题与解决方案

5.1 无限循环

问题: 循环条件永远为真,导致程序陷入无限循环 解决方案: 确保循环条件最终能为假,或使用 break 语句退出循环

 // 错误示例
 while (1) {
  printf("This will run forever\n");
 }
 // 正确示例
 int count = 0;
 while (1) {
  printf("Count: %d\n", count);
  count++;
  if (count >= 10) {
  break;
  }
 }

5.2 循环条件错误

问题: 循环条件设置错误,导致循环次数不符合预期 解决方案: 仔细检查条件,确保逻辑正确

 // 错误示例:应该是 i < 10,而不是 i <= 10
 for (int i = 0; i <= 10; i++) {
  printf("%d ", i); // 会打印 0-10,共 11 个数
 }
 // 正确示例
 for (int i = 0; i < 10; i++) {
  printf("%d ", i); // 打印 0-9,共 10 个数
 }

5.3 边界条件处理

问题: 循环边界条件处理不当,导致数组越界或其他错误 解决方案: 确保循环变量在有效范围内

 // 错误示例:可能导致数组越界
 int arr[5] = {1, 2, 3, 4, 5};
 for (int i = 0; i <= 5; i++) {
  printf("%d ", arr[i]); // 访问 arr[5] 越界
 }
 // 正确示例
 int arr[5] = {1, 2, 3, 4, 5};
 for (int i = 0; i < 5; i++) {
  printf("%d ", arr[i]);
 }

5.4 switch 语句缺少 break

问题: case 语句后缺少 break,导致穿透现象 解决方案: 为每个 case 语句添加 break,除非需要穿透

 // 错误示例:缺少 break
 switch (grade) {
  case 'A':
  printf("Great!\n");
  case 'B':
  printf("Good!\n"); // 当 grade 为 'A' 时也会执行
  break;
 }
 // 正确示例
 switch (grade) {
  case 'A':
  printf("Great!\n");
  break;
  case 'B':
  printf("Good!\n");
  break;
 }

5.5 嵌套过深

问题: 循环条件嵌套过深,代码可读性差 解决方案: 将嵌套的代码重构为函数

 // 嵌套过深的示例
 for (int i = 0; i < 10; i++) {
  if (i % 2 == 0) {
  for (int j = 0; j < 5; j++) {
  if (j > 2) {
  // 处理逻辑
  }
  }
  }
 }
 // 重构为函数
 void process_even(int i) {
  for (int j = 0; j < 5; j++) {
  if (j > 2) {
  // 处理逻辑
  }
  }
 }
 // 主函数
 for (int i = 0; i < 10; i++) {
  if (i % 2 == 0) {
  process_even(i);
  }
 }

6. 控制流的高级应用

6.1 循环的替代方案

6.1.1 使用 goto 实现循环

 #include <stdio.h>
 int main() {
  int i = 0;
  loop:
  if (i < 10) {
  printf("%d ", i);
  i++;
  goto loop;
  }
  printf("\n");
  return 0;
 }

6.1.2 使用递归代替循环

 #include <stdio.h>
 void print_numbers(int n) {
  if (n < 0) {
  return;
  }
  print_numbers(n - 1);
  printf("%d ", n);
 }
 int main() {
  print_numbers(9);
  printf("\n");
  return 0;
 }

6.2 复杂条件的处理

6.2.1 使用逻辑运算符组合条件

 #include <stdio.h>
 int main() {
  int age = 25;
  int has_license = 1;
  int has_car = 1;
  // 复杂条件
  if (age >= 18 && has_license && has_car) {
  printf("You can drive\n");
  } else if (age >= 18 && has_license) {
  printf("You can drive if you have a car\n");
  } else if (age >= 18) {
  printf("You need a license to drive\n");
  } else {
  printf("You are too young to drive\n");
  }
  return 0;
 }

6.2.2 使用布尔函数简化条件

 #include <stdio.h>
 int is_even(int n) {
  return n % 2 == 0;
 }
 int is_positive(int n) {
  return n > 0;
 }
 int main() {
  int number = 4;
  if (is_even(number) && is_positive(number)) {
  printf("%d is a positive even number\n", number);
  }
  return 0;
 }

6.3 状态机的实现

 #include <stdio.h>
 int main() {
  enum State {
  STATE_START,
  STATE_READING,
  STATE_PROCESSING,
  STATE_FINISHED
  };
  enum State current_state = STATE_START;
  int data_processed = 0;
  int max_data = 5;
  while (current_state != STATE_FINISHED) {
  switch (current_state) {
  case STATE_START:
  printf("Starting process\n");
  current_state = STATE_READING;
  break;
  case STATE_READING:
  printf("Reading data\n");
  current_state = STATE_PROCESSING;
  break;
  case STATE_PROCESSING:
  printf("Processing data %d\n", data_processed);
  data_processed++;
  if (data_processed >= max_data) {
  current_state = STATE_FINISHED;
  } else {
  current_state = STATE_READING;
  }
  break;
  case STATE_FINISHED:
  printf("Process finished\n");
  break;
  }
  }
  return 0;
 }

7. 代码优化技巧

7.1 循环优化

7.1.1 减少循环内计算

 // 优化前
 for (int i = 0; i < strlen(s); i++) {
  // 每次循环都计算 strlen(s)
 }
 // 优化后
 int len = strlen(s);
 for (int i = 0; i < len; i++) {
  // 只计算一次 strlen(s)
 }

7.1.2 使用递增而非递减

 // 优化前
 for (int i = n; i >= 0; i--) {
  // 循环体
 }
 // 优化后(某些架构上更高效)
 for (int i = 0; i <= n; i++) {
  // 循环体
 }

7.1.3 展开循环

 // 优化前
 for (int i = 0; i < 4; i++) {
  process(i);
 }
 // 优化后(展开循环)
 process(0);
 process(1);
 process(2);
 process(3);

7.2 条件优化

7.2.1 利用短路求值

 // 优化前
 if (ptr != NULL) {
  if (ptr->value == 5) {
  // 处理逻辑
  }
 }
 // 优化后
 if (ptr != NULL && ptr->value == 5) {
  // 处理逻辑
 }

7.2.2 条件顺序优化

 // 优化前(假设 ptr == NULL 的概率较高)
 if (ptr->value == 5 && ptr != NULL) {
  // 可能会崩溃
 }
 // 优化后
 if (ptr != NULL && ptr->value == 5) {
  // 更安全,利用短路求值
 }

7.3 控制流优化示例

 #include <stdio.h>
 // 优化前:多个 if-else 嵌套
 int get_grade_point(char grade) {
  if (grade == 'A') {
  return 4;
  } else if (grade == 'B') {
  return 3;
  } else if (grade == 'C') {
  return 2;
  } else if (grade == 'D') {
  return 1;
  } else {
  return 0;
  }
 }
 // 优化后:使用 switch 语句
 int get_grade_point_optimized(char grade) {
  switch (grade) {
  case 'A': return 4;
  case 'B': return 3;
  case 'C': return 2;
  case 'D': return 1;
  default: return 0;
  }
 }
 int main() {
  char grade = 'B';
  printf("Grade point: %d\n", get_grade_point(grade));
  printf("Grade point (optimized): %d\n", get_grade_point_optimized(grade));
  return 0;
 }

更新日志 (Changelog)

  • 2026-04-05: 拆分控制详解
  • 2026-04-05: 扩写内容增加详细的代码示例、使用方法、最佳实践和常见问题解决方案

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式