21 程序控制语句详解:循环控制(while、do-while、for、循环机制与原理、嵌套循环)
1 循环控制语句
在 C 语言中,循环控制是流程控制的关键组成部分,它使得一段代码能够在满足特定条件时重复执行。借助循环结构,开发者可以编写出简洁且高效的代码来处理重复性任务。C 语言提供了多种常用的循环控制语句,如 while 循环、do...while 循环和 for 循环。这些循环语句能够有效地重复执行一段代码,直至某一条件不再满足,尤其适用于需要多次迭代的任务,即便每次迭代的数据或条件有所差异。每种循环结构都有其特定的应用场景和语法特点,合理运用它们可以大大提升代码的可读性和执行效率。
2 while 循环
2.1 语法格式
while (循环条件表达式)
{循环体语句;
}
- 当循环条件表达式的结果为真(非 0)时,执行循环体语句。
- 每次执行完循环体后,会再次判断循环条件,若条件仍为真,则继续执行循环体,直到条件变为假(0)时,循环停止。
- 简而言之,while 循环是先判断条件,条件满足时才执行循环体,即 “先判断后执行”。
- 为了避免出现无限循环(即死循环),循环条件的设计至关重要。应确保随着每次循环迭代,条件会逐渐趋向于变为假。
- 如果 while 语句后面的循环体只包含一条语句,语法上允许省略花括号 {},但为了提高代码的可读性和避免潜在错误,建议始终保留花括号。
2.2 功能流程图
2.3 计数循环
实现原则
在 C 语言中使用 while 实现计数循环时,需遵循以下三个基本原则:
1. 初始化循环变量
在进入 while 循环之前,必须为循环变量赋予一个初始值。这个初始值通常代表计数循环的起点。例如,若要从 1 数到 10,就应在循环开始前将循环变量(如命名为 count)初始化为 1。这一初始化步骤确保了循环有一个明确的起始点,能够按照预定的方式开始计数。
2. 循环变量比较作为循环条件
while 循环的循环条件是一个布尔表达式,用于决定循环是否继续执行。在计数循环中,该条件通常涉及对循环变量的比较。例如,若希望一直执行循环体,直到循环变量达到或超过某个特定值,那么循环条件可能类似 count <= 10。这意味着只要 count 的值小于或等于 10,循环就会持续执行。此条件确保了循环能够按照预定的次数进行。
3. 更新循环变量
在循环体的末尾(或在循环体的某个适当位置,但必须确保在下一次迭代之前执行),必须更新循环变量的值。这通常是通过增加或减少循环变量(假设为 count)的值来实现的,具体取决于计数方向(向上计数还是向下计数)。例如,可以使用 count++(即 count = count + 1)或 count-- 来更新循环变量的值。这一更新步骤必不可少,因为它保证了每次循环迭代后,循环条件都会被重新评估。如果条件仍然为真,循环将继续执行;若循环变量没有变化,循环将无限期地继续下去,这通常被称为 “无限循环” 或 “死循环”。在编程中,应尽量避免出现无限循环,除非确实需要使用死循环来实现特定功能。
案例演示
案例 1:循环输出多条语句
使用 while 循环输出 10 次 "我第n天吃了n个韭菜馅的包子"。
#include <stdio.h>int main()
{int num = 1; // 初始化循环变量,从第 1 天开始计数// 当 num 小于等于 10 时,循环继续while (num <= 10){printf("我第%d天吃了%d个韭菜馅的包子 \n", num, num);num++; // 更新循环变量,为下一次循环准备条件}printf("循环结束后循环变量的值:%d\n", num); // 输出循环结束后的变量值return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 2:循环输出数字 7~15
使用 while 循环输出数字 7 到 15。
#include <stdio.h>int main()
{int n = 7; // 初始化循环变量,从 7 开始// 循环条件,当 n 小于等于 15 时继续循环while (n <= 15){printf("%d ", n);n++; // 更新循环变量,为下一次循环准备条件}printf("\n循环结束后循环变量的值:%d\n", n); // 输出循环结束后的变量值return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 3:倒序输出数字 56 ~ 43
使用 while 循环倒序输出数字 56 到 43。
#include <stdio.h>int main()
{int i = 56; // 初始化循环变量,从 56 开始倒序// 循环条件,当 i 大于等于 43 时继续循环while (i >= 43){printf("%d ", i);i--; // 更新循环变量,为下一次循环准备条件}printf("\n循环结束后循环变量的值:%d\n", i); // 输出循环结束后的变量值return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 4:输出 10(包括 10)以内所有的偶数
使用 while 循环输出 0 到 10 之间的所有偶数。
#include <stdio.h>int main()
{// 方法一:直接控制循环变量增量int i = 0;// 循环条件,当 i 小于等于 10 时继续循环while (i <= 10){printf("%d\t", i);i += 2; // 每次增加 2,跳过奇数}printf("\n循环结束后循环变量的值:%d\n", i); // 输出:12// 方法二:通过条件判断输出偶数int j = 0;// 循环条件,当 j 小于等于 10 时继续循环while (j <= 10){// 判断是否为偶数if (j % 2 == 0){printf("%d\t", j);}j++; // 每次增加 1,遍历所有数字}printf("\n循环结束后循环变量的值:%d\n", j); // 输出:11return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 5:计算 100 以内(包括 100)所有数字的和
使用 while 循环计算 1 到 100 的和。
#include <stdio.h>int main()
{int sum = 0; // 初始化累加和变量int i = 1; // 初始化循环变量,从 1 开始// 循环条件,当 i 小于等于 100 时继续循环while (i <= 100){sum += i; // 累加当前数字i++; // 更新循环变量}printf("100以内(包括100)所有数字的和是 %d \n", sum); // 输出:5050printf("循环结束后循环变量的值:%d", i); // 输出:101return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 6:计算 10 以内所有奇数的乘积
使用 while 循环计算 1 到 10 之间所有奇数的乘积。
#include <stdio.h>int main()
{// 方法一:直接跳过偶数int product = 1; // 初始化乘积变量int i = 1; // 初始化循环变量,从 1 开始// 循环条件,当 i 小于等于 10 时继续循环while (i <= 10){product *= i; // 累乘当前奇数i += 2; // 跳过偶数,直接处理下一个奇数}printf("10以内所有奇数的乘积是 %d \n", product); // 输出:945printf("循环结束后循环变量的值:%d \n", i); // 输出:11(9+2)// 方法二:通过条件判断输出奇数// 重新初始化变量i = 1; // 初始化循环变量,从 1 开始product = 1; // 初始化乘积变量// 循环条件,当 i 小于等于 10 时继续循环while (i <= 10){if (i % 2 != 0) // 判断是否为奇数{product *= i;}i++; // 遍历所有数字}printf("10以内所有奇数的乘积是 %d \n", product); // 输出:945printf("循环结束后循环变量的值:%d \n", i); // 输出:11(10+1)return 0;
}
程序在 VS Code 中的运行结果如下所示:
2.4 不确定循环
基本概念
不确定循环(动态条件循环)是指在循环开始前无法确定其具体执行次数的循环结构。其执行次数完全取决于循环条件的动态变化(例如用户输入、外部数据或实时状态)。这类循环通常用于处理未知或可变长度的任务,直到满足特定条件时终止。
- 动态条件:循环条件在每次迭代时重新评估(如 while (condition) 中的 condition)。
- 终止条件:循环在条件首次为假时终止。
- 典型场景:
- 用户登录验证(直到输入正确密码)。
- 实时数据采集(直到达到终止条件)。
- 游戏交互(直到玩家选择退出)。
案例演示
通过 while 循环实现密码验证功能,直到用户输入正确的 6 位数密码为止。
#include <stdio.h>int main()
{const int CORRECT_PWD = 123456; // 定义正确的密码常量int inputPwd = 0; // 初始化用户输入的密码变量// 注意,这里 inputPwd 必须初始化一个值,否则在第一次循环中会使用未初始化的值(垃圾值)// 使用 while 循环进行密码验证,直到输入的密码与正确密码一致// while 循环的条件是 inputPwd 不等于 CORRECT_PWD// 只要 inputPwd 不等于 CORRECT_PWD,就会继续循环// 当 inputPwd 等于 CORRECT_PWD 时,循环结束while (inputPwd != CORRECT_PWD){// 提示用户输入密码printf("请输入6位数字密码:");scanf("%d", &inputPwd);// 检查密码是否正确,是为了在密码错误时给出提示if (inputPwd != CORRECT_PWD){printf("密码错误,请重试。\n");}}printf("密码正确,欢迎回家!"); // 密码正确时输出欢迎信息return 0;
}
程序在 VS Code 中的运行结果如下所示:
3 do-while 循环
3.1 语法格式
do
{循环体语句; // 至少执行一次
} while (循环条件表达式); // 注意分号不可省略
- 先执行循环体,再判断条件。
- 即使条件最初为假,循环体也会至少执行一次。
- while 后必须加分号(;)。
- 如果 do 语句后面的循环体只包含一条语句,语法上允许省略花括号 {},但为了提高代码的可读性和避免潜在错误,建议始终保留花括号。
3.2 功能流程图
3.3 计数循环
使用 do-while 实现计数循环同样也需遵循以下三个原则:
- 初始化循环变量。
- 循环变量比较作为条件。
- 循环变量变化(自增/自减)。
案例 1:循环输出多条语句
使用 do-while 循环输出 10 次 "我第n天吃了n个韭菜馅的包子"。
#include <stdio.h>int main()
{int num = 1; // 初始化循环变量,从第 1 天开始计数// 先执行一次循环体,之后在条件为真时继续循环do{printf("我第%d天吃了%d个韭菜馅的包子 \n", num, num);num++; // 更新循环变量,为下一次循环准备条件} while (num <= 10); // 当 num 小于等于 10 时,循环继续printf("循环结束后循环变量的值:%d\n", num); // 输出循环结束后的变量值return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 2:循环输出数字 7~15
使用 do-while 循环输出数字 7 到 15。
#include <stdio.h>int main()
{int n = 7; // 初始化循环变量,从 7 开始// 使用 do-while 循环,先执行一次循环体,然后判断条件do{printf("%d ", n); // 输出当前 n 的值n++; // 更新循环变量} while (n <= 15); // 条件判断放在最后printf("\n循环结束后循环变量的值:%d\n", n); // 输出循环结束后的变量值return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 3:倒序输出数字 56 ~ 43
使用 do-while 循环倒序输出数字 56 到 43。
#include <stdio.h>int main()
{int i = 56; // 初始化循环变量,从 56 开始倒序// 使用 do-while 循环,先执行一次循环体,然后判断条件do{printf("%d ", i); // 输出当前 i 的值i--; // 更新循环变量(递减)} while (i >= 43); // 条件判断放在最后printf("\n循环结束后循环变量的值:%d\n", i); // 输出循环结束后的变量值return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 4:输出 10(包括 10)以内所有的偶数
使用 do-while 循环输出 0 到 10 之间的所有偶数。
#include <stdio.h>int main()
{// 方法一:直接控制循环变量增量(do-while)int i = 0; // 初始化循环变量,从 0 开始// 使用 do-while 循环,先执行一次循环体,然后判断条件do{printf("%d\t", i);i += 2; // 每次循环将 i 增加 2} while (i <= 10);printf("\n循环结束后循环变量的值:%d\n", i); // 输出:12// 方法二:通过条件判断输出偶数(do-while)int j = 0; // 初始化循环变量,从 0 开始// 使用 do-while 循环,先执行一次循环体,然后判断条件do{// 判断 j 是否为偶数if (j % 2 == 0){printf("%d\t", j);}j++; // 每次循环将 j 增加 1} while (j <= 10);printf("\n循环结束后循环变量的值:%d\n", j); // 输出:11return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 5:计算 100 以内(包括 100)所有数字的和
使用 do-while 循环计算 1 到 100 的和。
#include <stdio.h>int main()
{int sum = 0; // 初始化累加和变量int i = 1; // 初始化循环变量,从 1 开始// do-while 循环先执行一次循环体,然后判断条件do{sum += i; // 累加当前数字i++; // 更新循环变量} while (i <= 100);printf("100以内(包括100)所有数字的和是 %d \n", sum); // 输出:5050printf("循环结束后循环变量的值:%d\n", i); // 输出:101return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 6:计算 10 以内所有奇数的乘积
使用 do-while 循环计算 1 到 10 之间所有奇数的乘积。
#include <stdio.h>int main()
{// 方法一:直接跳过偶数(do-while)int product = 1; // 初始化乘积变量为 1int i = 1; // 初始化循环变量,从 1 开始// 使用 do-while 循环,先执行一次循环体,然后判断条件do{product *= i; // 计算乘积i += 2; // 每次循环将 i 增加 2} while (i <= 10);printf("10以内所有奇数的乘积是 %d \n", product); // 输出:945printf("循环结束后循环变量的值:%d \n", i); // 输出:11// 方法二:通过条件判断输出奇数(do-while)i = 1; // 重新初始化循环变量product = 1; // 重新初始化乘积变量为 1// 使用 do-while 循环,先执行一次循环体,然后判断条件do{// 判断 i 是否为奇数if (i % 2 != 0){product *= i;}i++;} while (i <= 10);printf("10以内所有奇数的乘积是 %d \n", product); // 输出:945printf("循环结束后循环变量的值:%d \n", i); // 输出:11return 0;
}
程序在 VS Code 中的运行结果如下所示:
3.4 不确定循环
案例:通过 do-while 循环实现密码验证功能,直到用户输入正确的 6 位数密码为止。
#include <stdio.h>int main()
{const int CORRECT_PWD = 123456; // 定义正确的密码常量int inputPwd = 0; // 初始化用户输入的密码变量// 注意,这里 inputPwd 必须初始化一个值,否则在第一次循环中会使用未初始化的值(垃圾值)// 使用 do-while 循环进行密码验证,至少执行一次循环体do{// 提示用户输入密码printf("请输入6位数字密码:");scanf("%d", &inputPwd);// 检查密码是否正确if (inputPwd != CORRECT_PWD){printf("密码错误,请重试。\n"); // 如果密码错误,输出提示信息}} while (inputPwd != CORRECT_PWD); // 如果密码错误,继续循环printf("密码正确,欢迎回家!"); // 密码正确时输出欢迎信息return 0;
}
程序在 VS Code 中的运行结果如下所示:
3.5 与 while 循环的区别
特性 | while 循环 | do-while 循环 |
---|---|---|
语法结构 | while (条件) { 循环体 } | do { 循环体 } while (条件); |
执行顺序 | 先判断条件,再执行循环体 | 先执行循环体,再判断条件 |
至少执行次数 | 0 次(条件初始为假时不执行) | 1 次(无论条件是否为真) |
适用场景 | 条件满足时才执行循环体(如遍历数组) | 必须至少执行一次操作(如用户输入验证) |
下面让我们通过一个程序来进一步理解两者的差异及注意事项:
#include <stdio.h>int main()
{// while 循环:条件初始为假,不执行int n = 10;while (n > 10){printf("while: %d\n", n); // 不执行n++; // 不执行}// do-while 循环:条件初始为假,仍执行一次n = 10;do{printf("do-while: %d\n", n); // 第一次输出 10n++; // 每次循环将 n 增加 1// 执行后 n 变为 11,条件 n > 10 恒为真,导致死循环。// 输出:持续打印递增的 n 值(如 10, 11, 12, ...),需按 Ctrl+C 终止程序。} while (n > 10); // 死循环(需手动终止)return 0;
}
程序在 VS Code 中的运行结果如下所示:
建议:
始终检查循环条件是否可能为假,避免逻辑错误;死循环时用 Ctrl + C 终止。
4 for 循环
4.1 语法格式
for (循环变量初始化; 循环条件表达式; 循环变量变化)
{循环语句; // 循环体
}
- 循环变量初始化:
- 仅在循环开始时执行一次,用于初始化循环控制变量(如 int i = 0)。
- 循环条件表达式:
- 每次循环迭代前评估,若为真(非零值),执行循环体;若为假(零值),退出循环。
- 循环变量变化:
- 每次循环体执行后执行,通常用于更新循环控制变量(如 i++),为下一次迭代做准备。
- 如果 for 语句后面的循环体只包含一条语句,语法上允许省略花括号 {},但为了提高代码的可读性和避免潜在错误,建议始终保留花括号。
4.2 功能流程图
for 循环的执行步骤如下:
- 初始化:执行循环变量初始化(仅一次)。
- 条件检查:评估循环条件表达式:
- 若为真,执行循环体;
- 若为假,退出循环。
- 执行循环体:运行循环语句。
- 更新变量:执行循环变量变化。
- 重复:返回步骤 2,直到条件为假。
4.3 计数循环
使用 for 实现计数循环同样也需遵循以下三个原则:
- 初始化循环变量:明确起始值(如 int i = 0)。
- 循环条件比较:基于循环变量判断(如 i < 10)。
- 更新循环变量:确保变量变化(如 i++)。
案例 1:循环输出多条语句
使用 for 循环输出 10 次 "我第n天吃了n个韭菜馅的包子"。
#include <stdio.h>int main()
{for (int num = 1; num <= 10; num++){printf("我第%d天吃了%d个韭菜馅的包子 \n", num, num);}// 注意:num 在 for 循环结束后会超出作用域// printf("循环结束后循环变量的值:%d\n", num); // 这行代码会报错,因为 num 超出了作用域return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 2:循环输出数字 7~15
使用 for 循环输出数字 7 到 15。
#include <stdio.h>int main()
{int n; // 在 for 循环外面声明循环变量for (n = 7; n <= 15; n++){printf("%d ", n);}// 注意:n 在 for 循环结束后仍然在作用域内// 这行代码不会报错,因为 n 在 for 循环外面声明// 但是 n 的值会是循环结束后的值printf("\n循环结束后循环变量的值:%d\n", n); // 输出:16return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 3:倒序输出数字 56 ~ 43
使用 for 循环倒序输出数字 56 到 43。
#include <stdio.h>int main()
{int i = 56; // 初始化循环变量// 如果循环变量在 for 循环外面声明// 那么在 for() 可以省略初始化部分// 但是仍需 ; 分号隔开for (; i >= 43; i--){printf("%d ", i);}printf("\n循环结束后循环变量的值:%d\n", i); // 此时 i = 42return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 4:输出 10(包括 10)以内所有的偶数
使用 for 循环输出 0 到 10 之间的所有偶数。
#include <stdio.h>int main()
{// 方法一:直接控制循环变量增量(for 循环)int i;for (i = 0; i <= 10; i += 2) // i+=2 表示每次循环 i 的值增加 2{printf("%d\t", i);}printf("\n循环结束后循环变量的值:%d\n", i); // 输出:12// 方法二:通过条件判断输出偶数(for 循环)int j;for (j = 0; j <= 10; j++){// 如果 j 除以 2 的余数为 0,则 j 是偶数if (j % 2 == 0){printf("%d\t", j);}}printf("\n循环结束后循环变量的值:%d\n", j); // 输出:11return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 5:计算 100 以内(包括 100)所有数字的和
使用 for 循环计算 1 到 100 的和。
#include <stdio.h>int main()
{int sum = 0; // 初始化累加和变量int i; // 声明循环变量 ifor (i = 1; i <= 100; i++) // 控制从 1 到 100{sum += i; // 累加当前数字}printf("100以内(包括100)所有数字的和是 %d \n", sum); // 输出:5050printf("循环结束后循环变量的值:%d\n", i); // 输出:101return 0;
}
程序在 VS Code 中的运行结果如下所示:
案例 6:计算 10 以内所有奇数的乘积
使用 for 循环计算 1 到 10 之间所有奇数的乘积。
#include <stdio.h>int main()
{// 方法一:直接跳过偶数(使用 for)int product1 = 1; // 初始化乘积变量for (int i = 1; i <= 10; i += 2) // i+=2 表示每次循环 i 的值增加 2{product1 *= i;}printf("10以内所有奇数的乘积是 %d \n", product1); // 输出:945// 方法二:通过条件判断输出奇数(使用 for)int product2 = 1; // 初始化乘积变量for (int i = 1; i <= 10; i++) // i++ 表示每次循环 i 的值增加 1{// 如果 i 除以 2 的余数不为 0,则 i 是奇数if (i % 2 != 0){product2 *= i; // 累乘当前奇数}}printf("10以内所有奇数的乘积是 %d \n", product2); // 输出:945return 0;
}
程序在 VS Code 中的运行结果如下所示:
4.4 灵活用法与变体
for 循环的灵活性体现在其支持多种简写或变体结构,适用于不同场景。以下是常见的变体形式及使用场景。
省略初始化表达式
- 场景:循环变量已在外部初始化时使用。
int i = 0;
for (; i < 10; i++)
{ printf("%d ", i); // 输出:0 1 2 3 4 5 6 7 8 9
}
- 初始化 i 在循环外部完成,for 仅保留条件和更新部分。
省略循环条件表达式(无限循环)
- 场景:需循环执行直到满足特定条件(如用户输入或事件触发)。
for (i = 0; ; i++)
{ if (i >= 10) break; // 通过 break 退出循环printf("%d ", i); // 输出:0 1 2 3 4 5 6 7 8 9
}
- 省略条件表达式会导致无限循环,必须通过 break 或 return 退出。
省略迭代表达式
- 场景:迭代逻辑复杂,需在循环体内手动更新变量。
for (i = 0; i < 10;)
{printf("%d ", i); // 输出:0 2 4 6 8i += 2; // 手动更新变量
}
- 更新逻辑(如 i += 2)放在循环体内,适用于非均匀递增/递减的场景。
同时省略多个表达式(完全无限循环)
- 场景:需持续运行直到外部条件满足(如服务器监听)。
for (;;) // 无限循环
{ if (外部条件) break; // 必须通过 break 退出printf("运行中...\n");
}
- 省略所有表达式时,需在循环体内通过 break 退出,否则程序挂起。
同时初始化多个变量
- 场景:需同时控制多个循环变量(如二维遍历)。
// 使用逗号运算符初始化并更新多个变量
for (int x = 1, y = 10; x < 6 && y > 7; x++, y--)
{printf("%d %d\n", x, y); // 输出:1 10 → 2 9 → 3 8
}
- 逗号运算符分隔多个操作,逻辑运算符(如 &&、||)连接条件。
4.5 不确定循环
案例:通过 for 循环实现密码验证功能,直到用户输入正确的 6 位数密码为止。
#include <stdio.h>int main()
{const int CORRECT_PWD = 123456; // 正确密码int inputPwd; // 用户输入的密码// for 循环初始化为空,条件为密码不匹配,更新操作为空for (; inputPwd != CORRECT_PWD;){printf("请输入6位数字密码:");scanf("%d", &inputPwd);if (inputPwd != CORRECT_PWD){printf("密码错误,请重试。\n");}}printf("密码正确,欢迎回家!\n");return 0;
}
程序在 VS Code 中的运行结果如下所示:
以上程序也可以使用如下方法进行实现,代码如下所示:
#include <stdio.h>int main()
{const int CORRECT_PWD = 123456; // 正确的密码int inputPwd = 0; // 用户输入的密码// for 循环的条件始终为真,直到输入正确的密码才退出循环// 这里的 for 循环没有初始化和更新操作for (;;){printf("请输入6位数字密码:");scanf("%d", &inputPwd);// 检查输入的密码是否正确if (inputPwd == CORRECT_PWD){break; // 如果密码正确,跳出循环}else{printf("密码错误,请重试。\n");}}printf("密码正确,欢迎回家!\n");return 0;
}
5 嵌套循环
5.1 基本概念
嵌套循环是指将一个循环结构放在另一个循环体内,形成多层循环。
常用的循环结构(for、while、do…while)均可作为外层或内层循环。
建议嵌套层数不超过 3 层,过多会降低代码可读性。
5.2 执行次数
- 嵌套循环结构:外层循环每执行一次,内层循环会完整执行一轮。
- 执行次数:若外层循环执行 m 次,内层循环执行 n 次,则内层循环体共执行 m * n 次。
#include <stdio.h>int main()
{int i, j, counter = 0; // 声明变量 i、j 和计数器 counter// 外层循环控制行数for (i = 1; i <= 5; i++) // 外层循环(5次){// 内层循环控制每行的列数for (j = 1; j <= 4; j++) // 内层循环(4次){printf("(%d, %d) ", i, j);counter++;}printf("\n"); // 每行结束后换行}printf("Total iterations: %d\n", counter); // 输出:20return 0;
}
程序在 VS Code 中的运行结果如下所示:
5.3 案例:打印二维坐标
通过嵌套循环遍历行和列,输出坐标格式 [行,列]。
#include <stdio.h>int main()
{int rows, cols; // 声明变量 rows 和 cols,用于存储行数和列数printf("请输入行数:");scanf("%d", &rows);printf("请输入列数:");scanf("%d", &cols);for (int i = 0; i < rows; i++) // 控制行数{for (int j = 0; j < cols; j++) // 控制列数{printf("[%d,%d] ", i, j);}printf("\n"); // 每行结束后换行}return 0;
}
程序在 VS Code 中的运行结果如下所示:
5.4 案例:打印九九乘法表的多种形式
九九乘法表是嵌套循环的经典应用场景,通过调整循环变量的起始值、终止条件和输出格式,可以实现不同形式的乘法表。以下是四种常见形式的实现方法及逻辑解析。
左下直角三角形
逻辑实现:
- 外层循环:控制行数 i,从 1 到 9。
- 内层循环:控制每行的列数 j,从 1 到 i(列数 ≤ 行号)。
- 输出格式:每列输出 j*i=乘积,用制表符 \t 分隔。
示例代码:
#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;
}
左上直角三角形
逻辑实现:
- 方法1:外层循环倒序(i 从 9 到 1),内层循环列数 j 从 1 到 i。
- 方法2:外层循环正序(i 从 1 到 9),内层循环列数 j 从 1 到 10-i。
示例代码:
#include <stdio.h>int main()
{// 方法1:外层循环倒序for (int i = 9; i >= 1; i--) // 外层循环:行数{for (int j = 1; j <= i; j++) // 内层循环:列数{printf("%d*%d=%d\t", j, i, i * j);}printf("\n");}printf("\n");// 方法2:内层循环条件调整for (int i = 1; i <= 9; i++) // 外层循环:行数{for (int j = 1; j <= 10 - i; j++) // 内层循环:列数{printf("%d*%d=%d\t", j, 10 - i, (10 - i) * j);}printf("\n");}return 0;
}
右下直角三角形
逻辑实现:
- 前导空格:每行前导空格数 = 9 - i(通过内层循环打印制表符 \t 实现)。
- 乘法表达式:列数 j 从 1 到 i,输出格式与左下直角三角形相同。
示例代码:
#include <stdio.h>int main()
{for (int i = 1; i <= 9; i++) // 外层循环:行数{for (int j = 1; j <= 9 - i; j++) // 打印前导空格{printf("\t");}for (int j = 1; j <= i; j++) // 内层循环:列数 ≤ 行号{printf("%d*%d=%d\t", j, i, i * j);}printf("\n");}return 0;
}
右上直角三角形
逻辑实现:
- 外层循环倒序:行号 i 从 9 到 1。
- 前导空格:每行前导空格数 = 9 - i。
- 乘法表达式:列数 j 从 1 到 i。
或者
- 外层循环正序:行号 i 从 1 到 9。
- 前导空格:每行前导空格数 = i - 1。
- 乘法表达式:列数 j 从 1 到 10 - i。
示例代码:
#include <stdio.h>int main()
{// 方法一for (int i = 9; i >= 1; i--) // 外层循环:行数{for (int j = 1; j <= 9 - i; j++) // 打印前导空格{printf("\t");}for (int j = 1; j <= i; j++) // 打印乘法表达式{printf("%d*%d=%d\t", j, i, i * j);}printf("\n");}printf("\n");// 方法二for (int i = 1; i <= 9; i++) // 外层循环:行数{for (int k = 1; k <= i - 1; k++) // 打印前导空格{printf("\t");}for (int j = 1; j <= (10 - i); j++) // 打印乘法表达式{printf("%d*%d=%d\t", j, (10 - i), j * (10 - i));}printf("\n");}return 0;
}