欢迎光临
我们一直在努力

C语言学习笔记20260620-数字筛选算法:排除4的倍数与含4数字

C语言学习笔记20260620-数字筛选算法:排除4的倍数与含4数字

一、学习目标

掌握在C语言中处理“数字特征筛选”类问题的多种编程思路,包括数学取模运算、函数封装思想以及字符串处理技巧。通过对比三种不同的实现方法,深入理解底层算法逻辑与代码可读性之间的权衡。

二、问题拆解与核心逻辑

本题要求输出 1 到 n 之间既不是 4 的倍数,也不包含数字 4 的整数。解决该问题需要处理两个独立的判断条件:

  • 数学条件:判断当前数字 i 是否能被 4 整除(i % 4 == 0)。
  • 数位条件:判断当前数字 i 的十进制表示中是否包含数字 4。
  • 只要满足任意一个条件,该数字就需要被过滤掉。

    三、方法一:临时变量拆数法(数学取模)

    3.1 核心思路

    利用数学中的“取模(%)”和“整除(/)”运算,从低位到高位逐位拆解数字,检查每一位是否等于 4。

    3.2 代码解析

    for (int i = 1; i <= n; i++)
    {
    if (i % 4 == 0) continue; // 提前过滤掉4的倍数
    int tmp = i;
    int has4 = 0; // 标记变量
    while (tmp > 0)
    {
    if (tmp % 10 == 4) // 取出当前最低位判断
    {
    has4 = 1;
    break; // 找到4立即跳出循环,提高效率
    }
    tmp /= 10; // 去掉最低位,准备判断下一位
    }
    if (has4 == 0)
    printf("%d\\n", i);
    }

    3.3 关键细节与优化

    • 保护原始数据:使用临时变量 tmp 来承接 i 的值进行拆解,避免直接修改循环变量 i 导致死循环或逻辑错误。
    • 循环终止条件:while (tmp > 0) 是拆数法的核心。当 tmp 变为 0 时,说明所有位数都已检查完毕。如果错误地写成 tmp >= 0,当 tmp 为 0 时会陷入死循环。
    • 提前终止:一旦发现某一位是 4,立即使用 break 跳出循环,无需继续检查剩余的高位。

    四、方法二:封装判断函数(模块化思想)

    4.1 核心思路

    将“判断是否包含数字4”这一独立逻辑抽取为一个单独的函数 containFour,使主函数 main 的逻辑更加清晰。

    4.2 代码解析

    // 判断x是否包含数字4,含4返回1,不含返回0
    int containFour(int x)
    {
    while (x > 0)
    {
    if (x % 10 == 4)
    return 1; // 找到4直接返回真
    x /= 10;
    }
    return 0; // 遍历完所有位都没找到4,返回假
    }

    // 主函数逻辑极其简洁
    for (int i = 1; i <= n; i++)
    {
    // 两个条件满足任意一个就跳过
    if (i % 4 == 0 || containFour(i))
    continue;
    printf("%d\\n", i);
    }

    4.3 优势分析

    • 可读性强:主循环中的 if 条件读起来就像自然语言(如果是4的倍数 或 包含4,则跳过)。
    • 复用性高:如果后续题目要求判断是否包含数字 7,只需修改或新增一个函数,无需改动主循环逻辑。
    • 逻辑解耦:将复杂的拆数逻辑隐藏在函数内部,降低了主函数的认知负担。

    五、方法三:字符串处理法(类型转换)

    5.1 核心思路

    将数字转换为字符串,把“数位检查”问题转化为“字符查找”问题。利用 sprintf 进行数字到字符串的转换,再遍历字符串查找字符 ‘4’。

    5.2 代码解析

    char buf[20]; // 存放数字转成的字符串
    for (int i = 1; i <= n; i++)
    {
    if (i % 4 == 0) continue;
    sprintf(buf, "%d", i); // 将整数 i 格式化输出到字符数组 buf 中
    int has4 = 0;
    for (int j = 0; buf[j] != '\\0'; j++)
    {
    if (buf[j] == '4') // 注意这里比较的是字符 '4'
    {
    has4 = 1;
    break;
    }
    }
    if (!has4)
    printf("%d\\n", i);
    }

    5.3 适用场景与局限

    • 适用场景:当判断条件变得复杂时(例如:包含连续两个4,或者包含4或7),字符串处理法往往比数学拆数法更直观,且不易出错。
    • 局限性:涉及类型转换和额外的字符数组内存分配,运行效率略低于纯数学运算。

    在实际编程与算法竞赛中,方法2(封装函数)通常是最佳实践,它兼顾了代码的整洁度与执行效率。而方法1是理解底层数位拆解的基础,方法3则在处理复杂数位规则时提供了另一种灵活的解题视角。

    赞(0)
    未经允许不得转载:171主机测评 » C语言学习笔记20260620-数字筛选算法:排除4的倍数与含4数字
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址