C语言 do...while、循环控制及goto语句详解与实战

Ruby
Ruby
发布时间:2026-10-16 | 4人浏览过
原创

do...while 循环是 C 语言中唯一一种至少执行一次循环体的结构。本文将讲解其语法、执行流程,重点分析 break 和 continue 在其中的行为差异(特别是 continue 易导致的死循环),并通过阶乘、二分查找等经典练习掌握循环逻辑,最后介绍 goto 语句的特定用途。

do...while 循环的核心逻辑

第1步:掌握 do...while 的基本语法

do...while 循环的特点是先执行循环体,再判断条件。只要条件为真(非0),就继续执行;否则退出循环。其标准语法结构如下:

do {
    循环语句;
} while(表达式);

注意: while(表达式) 后面必须加分号 ;,这是新手常犯的错误。

第2步:理解执行流程与适用场景

由于先执行后判断,do...while 循环体内的代码至少会执行一次。这一特性使其非常适合用于“无论结果如何,至少执行一次”的场景,例如菜单选择界面、游戏开始界面或用户登录验证。

基本示例:展示即使初始条件不满足,循环体仍执行一次的情况。

#include <stdio.h>
int main()
{
    int i = 10;
    do
    {
        printf("%d\n", i);
    } while (i < 10); // 初始 i=10,条件 i<10 为假,但上面仍打印了一次 10
    return 0;
}

第3步:区分 break 与 continue 的行为

在 do...while 中,break 和 continue 的行为与其他循环类似但有细微差别,需特别注意 continue 可能引发的死循环。

1. break 语句: 作用是完全终止并跳出当前所在的整个循环层。当执行到 break 时,程序直接跳到循环体结束后的下一条语句。

#include <stdio.h>
int main()
{
    int i = 0;
    do
    {
        if (5 == i)
            break; // 当 i 为 5 时跳出循环
        printf("%d\n", i);
        i++;
    } while (i < 10);
    return 0;
}
// 输出结果: 0 1 2 3 4

2. continue 语句: 作用是跳过本次循环中剩余的代码,直接进入 while(表达式) 的条件判断。
⚠️ 高风险提示: 如果在 i++ 之前使用了 continue,且变量 i 没有在其他地方递增,条件判断可能会一直成立,导致死循环。

#include <stdio.h>
int main()
{
    int i = 0;
    do
    {
        if (5 == i)
            continue; // 跳到 while(i<10),此时 i 仍为 5,条件永远成立!
        printf("%d\n", i);
        i++; // i++ 被跳过,i 永远无法大于等于 5
    } while (i < 10);
    return 0;
}

循环综合实战练习

通过以下经典题目,将分支结构与循环结合使用,巩固编程思维。

第1步:计算阶乘及其累加和

任务A: 计算 n 的阶乘。利用 for 循环从 1 乘到 n。

#include <stdio.h>
int main()
{
    int n = 0;
    int ret = 1; // 结果变量初始化
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        ret *= i;
    }
    printf("%d", ret);
    return 0;
}

任务B: 计算 1! + 2! + ... + 10!。关键在于维护一个中间结果 ret 存储当前的阶乘值,每次迭代更新后加到总和 sum 中。

#include <stdio.h>
int main()
{
    int sum = 0;
    int ret = 1; // 注意:如果外层用两个for循环,内层必须重置ret=1
    for (int i = 1; i <= 10; i++)
    {
        ret *= i;    // 累乘得到 i!
        sum += ret;  // 累加到总和中
    }
    printf("%d", sum);
    return 0;
}

第2步:有序数组查找(二分法)

在有序数组中快速定位目标,核心思想是不断缩小搜索范围。定义左边界 left、右边界 right 和中间值 mid。

#include <stdio.h>
int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int left = 0;
    int right = sizeof(arr) / sizeof(arr[0]) - 1;
    int key = 7;
    int mid = 0;

    while (left <= right) // 关键终止条件
    {
        mid = (left + right) / 2;
        if (arr[mid] > key)
        {
            right = mid - 1; // 目标在左边,收缩右边界
        }
        else if (arr[mid] < key)
        {
            left = mid + 1;  // 目标在右边,收缩左边界
        }
        else
        {
            break; // 找到目标
        }
    }

    if (left <= right)
        printf("找到了,下标是%d\n", mid);
    else
        printf("找不到\n");
    return 0;
}

第3步:模拟用户登录验证

限制尝试次数(如3次),并使用字符串比较函数 strcmp 进行密码比对。字符串不能直接用 == 比较。

#include <stdio.h>
#include <string.h>
int main()
{
    char psw[10] = "";
    int attempts = 0;
    
    for (attempts = 0; attempts < 3; ++attempts)
    {
        printf("请输入密码: ");
        scanf("%s", psw);
        if (strcmp(psw, "password") == 0)
        {
            break; // 密码正确,跳出循环
        }
    }

    if (attempts == 3)
        printf("次数耗尽,程序退出\n");
    else
        printf("登录成功\n");
    return 0;
}

第4步:完整项目 - 猜数字游戏

这是一个综合性小项目,结合了函数模块化、随机数生成 (rand(), srand())、switch-case 分支以及 do...while 菜单循环。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void menu() {
    printf("**************************\n");
    printf("******* 1. Play  *********\n");
    printf("******* 0. Exit  *********\n");
    printf("**************************\n");
}

void game() {
    int random_num = rand() % 100 + 1;
    int input = 0;
    while (1) {
        printf("请输入猜测的数字 >: ");
        scanf("%d", &input);
        if (input > random_num)
            printf("猜大了\n");
        else if (input < random_num)
            printf("猜小了\n");
        else {
            printf("恭喜你,猜对了!\n");
            break;
        }
    }
}

int main() {
    int input = 0;
    srand((unsigned int)time(NULL)); // 初始化随机数种子,只需调用一次
    
    do {
        menu();
        printf("请选择 >:");
        scanf("%d", &input);
        switch (input) {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("输入错误,请重新输入!\n");
            break;
        }
    } while (input); // input != 0 则继续循环
    
    return 0;
}

关于 goto 语句的特殊用途

C语言提供 goto 语句用于无条件跳转至标记位置。虽然一般不建议随意使用,但在处理深层嵌套循环错误或资源释放时,它比多层 break 更清晰简洁。

典型场景: 一次性跳出两层或多层循环或处理复杂错误路径。

// 错误处理示例
for (...)
{
    for (...)
    {
        if (disaster)
            goto error; // 直接跳到底部错误处理区
    }
}
error:
    // 清理资源...
    return -1;

注意: 除非确实能简化复杂逻辑(如多层嵌套的退出),否则应优先使用结构化控制语句(如 while 配合标志位),以保持代码的可读性和可维护性。

以上就是C语言 do...while 循环、循环控制符及 goto 语句的详细内容,更多关于 C语言基础教程的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表