21 程序控制语句详解:循环控制(while、do-while、for、循环机制与原理、嵌套循环)

发布于:2025-05-29 ⋅ 阅读:(30) ⋅ 点赞:(0)

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); // 输出:11

    return 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); // 输出:5050
    printf("循环结束后循环变量的值:%d", i);               // 输出:101

    return 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); // 输出:945
    printf("循环结束后循环变量的值:%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); // 输出:945
    printf("循环结束后循环变量的值:%d \n", i);      // 输出:11(10+1)

    return 0;
}

        程序在 VS Code 中的运行结果如下所示:

2.4 不确定循环

基本概念

        不确定循环(动态条件循环)是指在循环开始前无法确定其具体执行次数的循环结构。其执行次数完全取决于循环条件的动态变化(例如用户输入、外部数据或实时状态)。这类循环通常用于处理未知或可变长度的任务,直到满足特定条件时终止。

  1. 动态条件:循环条件在每次迭代时重新评估(如 while (condition) 中的 condition)。
  2. 终止条件:循环在条件首次为假时终止
  3. 典型场景:
    1. 用户登录验证(直到输入正确密码)。
    2. 实时数据采集(直到达到终止条件)。
    3. 游戏交互(直到玩家选择退出)。

案例演示

        通过 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. 初始化循环变量
  2. 循环变量比较作为条件
  3. 循环变量变化(自增/自减)

案例 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); // 输出:11

    return 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); // 输出:5050
    printf("循环结束后循环变量的值:%d\n", i);             // 输出:101

    return 0;
}

        程序在 VS Code 中的运行结果如下所示:

案例 6:计算 10 以内所有奇数的乘积

        使用 do-while 循环计算 1 到 10 之间所有奇数的乘积。 

#include <stdio.h>

int main()
{
    // 方法一:直接跳过偶数(do-while)
    int product = 1; // 初始化乘积变量为 1
    int i = 1;       // 初始化循环变量,从 1 开始

    // 使用 do-while 循环,先执行一次循环体,然后判断条件
    do
    {
        product *= i; // 计算乘积
        i += 2;       // 每次循环将 i 增加 2
    } while (i <= 10);

    printf("10以内所有奇数的乘积是 %d \n", product); // 输出:945
    printf("循环结束后循环变量的值:%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); // 输出:945
    printf("循环结束后循环变量的值:%d \n", i);      // 输出:11

    return 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); // 第一次输出 10
        n++;                         // 每次循环将 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 循环的执行步骤如下:

  1. 初始化:执行循环变量初始化(仅一次)。
  2. 条件检查:评估循环条件表达式:
    • 若为真,执行循环体;
    • 若为假,退出循环。
  3. 执行循环体:运行循环语句。
  4. 更新变量:执行循环变量变化。
  5. 重复:返回步骤 2,直到条件为假。

4.3 计数循环

        使用 for 实现计数循环同样也需遵循以下三个原则:

  1. 初始化循环变量:明确起始值(如 int i = 0)
  2. 循环条件比较:基于循环变量判断(如 i < 10)
  3. 更新循环变量:确保变量变化(如 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); // 输出:16

    return 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 = 42

    return 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); // 输出:11

    return 0;
}

        程序在 VS Code 中的运行结果如下所示:

案例 5:计算 100 以内(包括 100)所有数字的和

        使用 for 循环计算 1 到 100 的和。

#include <stdio.h>

int main()
{
    int sum = 0; // 初始化累加和变量
    int i;       // 声明循环变量 i

    for (i = 1; i <= 100; i++) // 控制从 1 到 100
    {
        sum += i; // 累加当前数字
    }

    printf("100以内(包括100)所有数字的和是 %d \n", sum); // 输出:5050
    printf("循环结束后循环变量的值:%d\n", i);             // 输出:101

    return 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); // 输出:945

    return 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 8
    i += 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); // 输出:20

    return 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 案例:打印九九乘法表的多种形式

        九九乘法表是嵌套循环的经典应用场景,通过调整循环变量的起始值、终止条件和输出格式,可以实现不同形式的乘法表。以下是四种常见形式的实现方法及逻辑解析。

左下直角三角形

逻辑实现:

  1. 外层循环:控制行数 i,从 1 到 9。
  2. 内层循环:控制每行的列数 j,从 1 到 i(列数 ≤ 行号)。
  3. 输出格式:每列输出 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;
}

右下直角三角形 

逻辑实现:

  1. 前导空格:每行前导空格数 = 9 - i(通过内层循环打印制表符 \t 实现)
  2. 乘法表达式:列数 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;
}

右上直角三角形

逻辑实现:

  1. 外层循环倒序:行号 i 从 9 到 1。
  2. 前导空格:每行前导空格数 = 9 - i。
  3. 乘法表达式:列数 j 从 1 到 i。

        或者

  1. 外层循环正序:行号 i 从 1 到 9。
  2. 前导空格:每行前导空格数 = i - 1。
  3. 乘法表达式:列数 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;
}