前言
今晚收到母校的几个大一学弟学妹们的请求,说C语言中的for循环结构比较难理解,学校老师讲的不怎么听懂,因为之前看过我写的 【深入理解Java集合框架 - 零】 | 数组 的文章,深入浅出通俗易懂,希望给他们讲解下。所以连夜赶制了这篇文章,从各个角度深入剖析讲解,希望刚进入编程世界的小伙伴的能有所收获。
编程是一门实操性比较强的技术,纸上得来终觉浅,绝知此事要躬行。
操千曲而后晓声,观千剑而后识器。虐它千百遍方能通晓其真意。
一、概述
for循环是编程中最常用的循环结构,用于重复执行一段代码直到满足某个条件。
二、基本语法
for (初始化表达式; 条件表达式; 更新表达式) {
// 循环体
}
三、组成及执行流程
3.1、初始化表达式:
- 在
循环开始前执行一次。 - 通常用于
初始化一个计数器变量。 - 可以是
多条语句。 - 例如:
int i = 0。
3.2、条件表达式:
- 在
每次循环开始时判断。 - 若
条件表达式的值为真,则执行循环体。 - 若
条件表达式的值为假,则退出循环。 - 例如:
i < 10。
3.3、更新表达式:
- 在
每次循环体执行完毕后执行。 - 通常用于
更新计数器变量。 - 可以是
多条语句。 - 例如:
i++。
3.4、循环体:
- 包含在
{}大括号内的代码块,会在每次循环时执行。
四、与其他循环结构的对比
4.1、while 循环
while循环在每次循环开始时判断条件表达式,如果条件为真,则执行循环体。- 适用于
条件不确定的情况。
int main() {
int i = 0;
while (i < 5) {
printf("i = %d\n", i);
i++;
}
return 0;
}
4.2、do-while循环
do-while循环是至少执行一次循环体,然后在每次循环结束时判断条件表达式,如果条件为真,则继续执行循环体。- 适用于
需要至少执行一次的情况。
int main() {
int i = 0;
do {
printf("i = %d\n", i);
i++;
} while (i < 5);
return 0;
}
五、示例
5.1、基本的for循环:
int main() {
for (int i = 0; i < 5; i++) {
printf("i = %d\n", i);
}
return 0;
}
5.2、计算数组的和:
int main() {
int arr[] = {10, 20, 30, 40, 50};
int size = sizeof(arr) / sizeof(arr[0]);
int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
printf("数组的和: %d\n", sum); // 输出: 数组的和: 150
return 0;
}
5.3、倒序遍历数组:
int main() {
int arr[] = {10, 20, 30, 40, 50};
int size = sizeof(arr) / sizeof(arr[0]);
for (int i = size - 1; i >= 0; i--) {
printf("arr[%d] = %d\n", i, arr[i]);
}
return 0;
}
六、特殊用法
6.1、省略初始化表达式:
- 如果在
for循环外部已经初始化了计数器变量,可以省略初始化表达式。
int main() {
int i = 0;
for (; i < 5; i++) {
printf("i = %d\n", i);
}
return 0;
}
6.2、省略条件表达式:
- 如果省略条件表达式,
for循环将无限循环,除非在循环体内有break语句。
int main() {
for (int i = 0;; i++) {
if (i >= 5) {
break;
}
printf("i = %d\n", i);
}
return 0;
}
6.3、省略更新表达式:
- 如果在
循环体内已经更新了计数器变量,可以省略更新表达式。
int main() {
for (int i = 0; i < 5;) {
printf("i = %d\n", i);
i++;
}
return 0;
}
6.4、多个初始化及更新表达式:
- 可在
初始化表达式中初始化多个变量。 - 可在
更新表达式中更新多个变量。
int main() {
for (int i = 0, j = 10; i < 5; i++, j--) {
printf("i = %d, j = %d\n", i, j);
}
return 0;
}
6.5、死循环:
- 忘记
更新循环变量或更新方式错误可能导致死循环。
int main() {
for (int i = 0; i < 5; ) {
// 忘记更新 i
printf("i = %d\n", i);
}
return 0;
}
6.6、嵌套循环:
需求1:打印二维数组:
int main() {
// 定义一个二维数组
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 外层循环遍历行
for (int i = 0; i < 3; i++) {
// 内层循环遍历列
for (int j = 0; j < 4; j++) {
// 打印当前元素
printf("%d ", matrix[i][j]);
}
// 每打印完一行后换行
printf("\n");
}
return 0;
}
输出结果:
1 2 3 4
5 6 7 8
9 10 11 12
需求2:打印打印九九乘法表。
int main() {
// 外层循环控制行数
for (int i = 1; i <= 9; i++) {
// 内层循环控制列数
for (int j = 1; j <= i; j++) {
// 打印每一项乘法表达式
printf("%d * %d = %2d ", j, i, i * j);
}
// 每打印完一行乘法表后换行
printf("\n");
}
return 0;
}
输出结果:
1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81
需求3:打印1~100之间的素数。
- 素数的特点:
- 素数(
质数)是指在大于1的自然数中,除了1和它本身以外不再有其他因数的数。 - 换言之,若一个数只能
被1和它自己整除,那么这个数就是素数(要点1)。 - 奇偶性:除了
最小的素数2是唯一的偶数素数外,其余所有素数都是奇数(要点2)。
- 素数(
bool isPrime(int n) {
if (n <= 1) {
return false; // 1及以下的数不是素数
}
if (n == 2) {
return true; // 2是最小的素数
}
if (n % 2 == 0) {
return false; // 排除偶数
}
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return false; // 如果能被i整除,则不是素数
}
}
return true; // 如果没有找到能整除的数,则是素数
}
int main() {
printf("1到100之间的素数:\n");
//遍历2到100的数
for (int i = 2; i <= 100; i++) {
if (isPrime(i)) {
printf("%d ", i);
}
}
printf("\n");
return 0;
}
输出结果:
1到100之间的素数:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
思考:为什么使用 i*i <=n ?
- 数学原理:
- 如果一个数
n不是素数,那么它一定有一个不大于其平方根的因数。 - 假设
n有一个因数d,且d小于等于sqrt(n),那么n / d也是一个因数,且n / d大于等于sqrt(n)。 - 因此,如果
n有因数,那么至少有一个因数在[2, sqrt(n)]范围内。
- 如果一个数
- 优化效果:
- 使用
i * i <= n作为循环条件,可以将检查的范围从[2, n-1]缩小到[2, sqrt(n)]。 - 这
大大减少了需要检查的次数,特别是对于较大的n,这种优化效果非常明显。
- 使用
七、总结
for 循环是编程语言中非常强大和灵活的循环结构,适用于各种需要重复执行的场景。通过合理设置初始化表达式、条件表达式和更新表达式,可以实现复杂的逻辑。
初学者若想掌握好for循环,需要逐步的感悟代码的执行流程,彻底理解每一代码的作用,然后多练习和感悟,慢慢的就能熟练掌握了 !!!
码字不易,记得 关注 + 点赞 + 收藏 + 评论