C语言实现埃拉托斯特尼筛法

这段 C 语言代码实现了一个 埃拉托斯特尼筛法(Sieve of Eratosthenes) 的变种,用于 标记小于等于 n 的所有非素数(合数) ,并 打印出每个素数及其筛掉的倍数 。最后程序会不断读入用户输入的整数 x,并输出 prime[x] 的值,用来判断 x 是否为素数。

复制代码
#include<stdio.h>

int prime[100] = {0};

void init_prime(int n) {
    prime[0] = prime[1] = 1;
    for (int i = 2; i * i <= n; i++) {
        if (prime[i]) continue;
        printf("%d is prime : ", i);
        for (int j = i * i; j <= n; j += i) {
            prime[j] = 1;
            printf(" %d", j);
        }
        printf("\n");
    }
    return ;
}

int main() {
    init_prime(50);
    int x;
    while (scanf("%d", &x) != EOF) {
        printf("prime[%d] = %d\n", x, prime[x]);
    }
    return 0;
}

这个代码是什么意思,请你详细解答

🧠 整体逻辑概览

  • 使用一个全局数组 prime[100],初始化为全 0。
  • 数组含义: - prime[i] == 0 表示 i 是素数 ; - prime[i] == 1 表示 i 不是素数(被筛掉了)
  • init_prime(50):对 0~50 范围内的数进行筛法处理,并打印过程。
  • 主函数中循环读取输入,查询任意 x 是否为素数。

🔍 逐行详细解释

1. 头文件与全局变量

复制代码
复制代码
#include <stdio.h>

int prime[100] = {0};
  • 引入标准输入输出库。
  • 定义一个大小为 100 的整型数组 prime,所有元素初始化为 0。 - 这个数组将作为"筛子":下标代表数字,值代表是否为合数。

2. 筛法函数 init_prime(int n)

复制代码
复制代码
void init_prime(int n) {
    prime[0] = prime[1] = 1;
  • 0 和 1 不是素数,所以直接标记为 1(即"非素数")。
复制代码
复制代码
    for (int i = 2; i * i <= n; i++) {
  • i = 2 开始遍历到 √n(因为大于 √n 的合数一定已被更小的因子筛过)。
复制代码
复制代码
        if (prime[i]) continue;
  • 如果 prime[i] == 1,说明 i 已经被标记为合数,跳过。
  • 只有当 prime[i] == 0(即 i 是素数)时,才继续筛它的倍数。
复制代码
复制代码
        printf("%d is prime : ", i);
  • 打印当前素数 i
复制代码
复制代码
        for (int j = i * i; j <= n; j += i) {
            prime[j] = 1;
            printf(" %d", j);
        }
  • i*i 开始,把 i 的所有倍数(i*i, i*(i+1), ...)都标记为合数(prime[j] = 1)。
  • 同时打印这些被筛掉的数。

为什么从 i*i 开始? 因为小于 i*ii 的倍数(如 2*i, 3*i, ..., (i-1)*i)已经被更小的素数筛过了。

复制代码
复制代码
        printf("\n");
    }
    return ;
}
  • 每处理完一个素数,换行。

3. 主函数 main()

复制代码
复制代码
int main() {
    init_prime(50);
  • 对 0~50 的数执行筛法,并打印筛的过程。
复制代码
复制代码
    int x;
    while (scanf("%d", &x) != EOF) {
        printf("prime[%d] = %d\n", x, prime[x]);
    }
  • 循环读取用户输入的整数 x,直到遇到文件结束(EOF,比如在 Linux 下按 Ctrl+D,Windows 下按 Ctrl+Z)。
  • 输出 prime[x]: - 如果输出 0x 是素数; - 如果输出 1x 不是素数。
复制代码
复制代码
    return 0;
}

🖨️ 示例运行输出(部分)

假设你运行程序后输入:

复制代码
复制代码
2
4
17
25

可能看到的输出(筛法过程 + 查询结果):

复制代码
复制代码
2 is prime :  4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50
3 is prime :  9 12 15 18 21 24 27 30 33 36 39 42 45 48
5 is prime :  25 30 35 40 45 50
7 is prime :  49
prime[2] = 0
prime[4] = 1
prime[17] = 0
prime[25] = 1

注意:12、18、30 等数会被多个素数重复筛(这是正常的,但效率略低;可优化,但不影响正确性)。


⚠️ 潜在问题或注意事项

  1. 数组越界风险 : - prime 数组大小是 100,但 init_prime(50) 是安全的(只用到下标 0~50)。 - 但如果用户输入 x >= 100,比如 x = 150,就会访问 prime[150],导致未定义行为(可能崩溃或读到垃圾值) 。 - ✅ 建议加判断:if (x < 0 || x >= 100) { printf("Out of range\n"); continue; }

  2. 命名反直觉 : - prime[i] == 0 表示是素数,这容易让人困惑。 - 更常见的做法是叫 is_composite[]not_prime[],或者反过来:is_prime[i] = 1 表示是素数。

  3. 打印干扰逻辑: - 打印筛的过程是为了演示,实际使用筛法时通常不打印。


✅ 总结

这段代码的核心是:

  • 用埃拉托斯特尼筛法预处理出 0~50 范围内所有素数
  • 通过一个布尔数组(用 int 模拟)快速查询任意数是否为素数
  • 交互式地让用户测试查询结果

它是一个很好的 教学示例,展示了:

  • 筛法思想
  • 数组作为标记表的用法
  • C 语言的循环、条件、输入输出

如果你是为了学习素数判断或筛法,这段代码非常有价值!

相关推荐
catchadmin2 小时前
Laravel12 + Vue3 的免费可商用 PHP 管理后台 CatchAdmin V5.1.0 发布 新增 AI AGENTS 配置
开发语言·php
一颗青果2 小时前
auto | 尾置返回类型 | decltype | using | typedef
java·开发语言·算法
江君是实在人2 小时前
java jvm 调优
java·开发语言·jvm
kylezhao20193 小时前
C# 中实现自定义的窗口最大化、最小化和关闭按钮
开发语言·c#
一苓二肆3 小时前
PUMA机械臂matlab仿真正逆解与路径规划
开发语言·matlab
Frank_refuel3 小时前
C++之继承
开发语言·c++
sunfove3 小时前
Python 自动化实战:从识图点击、模拟真人轨迹到封装 EXE 全流程教学
开发语言·python·自动化
傻啦嘿哟3 小时前
Python网页自动化操作全攻略:从入门到实战
开发语言·python·自动化
sycmancia3 小时前
C语言学习06——函数的定义
c语言