欧拉素数筛选与命令行传参启动C程序

3 篇文章 0 订阅
2 篇文章 0 订阅

欧拉素数筛选与命令行传参启动C程序


不出所料,期末考试我选的就是素数筛选这道题
写了一下午,边学边写,现把成果发出来
有些逻辑还不是很好,不过就这样吧不改了

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <time.h>

#define MaxArray 100000001
extern char *optarg;
int Prime[MaxArray], PrimeCounter = 0;
bool Composite[MaxArray] = {false};

void eulerSieve (int N)
{
    for (int NumCounter = 2; NumCounter <= N; NumCounter++)
    {
        if (Composite[NumCounter] == false)
            Prime[PrimeCounter++] = NumCounter;
        
        for (int Poller = 0; Poller < PrimeCounter; Poller++)
        {
            if (NumCounter * Prime[Poller] > N)
                break;

            Composite[NumCounter * Prime[Poller]] = true;

            if (NumCounter % Prime[Poller] == 0)
                break;
        }
    }
}

int primeSieve (int start, int end)
{
    int s, e;
    clock_t st, et;

    if (start > end) {
        s = end;
        e = start;
    }
    else if (start == end) {
        printf ("\nThe start and end cannot be the same number.\n");
        return -1;
    }
    else {
        s = start;
        e = end;
    }
    
    st = clock();
    eulerSieve (e);
    et = clock();

    for (int Num = 0, Row = 1; Num < PrimeCounter;)
    {
        if (Prime[Num] < s)
            Num++;

        else
        {
            for (Num; Num < PrimeCounter; Num++, Row++)
            {
                printf ("%d\t", Prime[Num]);

                if (Row %10 == 0)
                printf ("\n");
            }
            break;
        }
    }

    printf ("\n\nIt took %.06f seconds to filter all prime numbers from %d to %d.\n"
    "Written by Aloento, Bye.\n\n", (double)(et-st)/CLOCKS_PER_SEC, s, e);

    return 0;
}

int isdigitstr (char *str)
{
    if (strspn(str, " 0123456789") == strlen(str))
        return atoi (str);
    else
    {
        printf ("Please enter a Positive Integer.\n");
        exit (-1);
    }
}

int help (char *name)
{
    printf ("usage: %s [-h] [-s] [-e]\n"
    "\n-h: Help to use Prime Sieve."
    "\n-s: The starting number for filtering, optional, default is 0."
    "\n-e: The number where the filtering ends, required.\n"
    "\nFor example: "
    "\n./%s -s 100 -e 200\n"
    "\nWritten by Aloento\n", name, name);

    return 1;
}

int menu (int argc, char *argv[])
{
    int opt = 0, start = 0, end = -1;

    while (EOF != (opt = getopt(argc, argv, "hs:e:")))
    {
        switch (opt)
        {
        case 's':
            start = isdigitstr (optarg);
            break;

        case 'e':
            end = isdigitstr (optarg);        
            return primeSieve (start, end);
            break;

        case '?':
            printf ("\nUnsupported parameters, Please check your input.\n");
        case 'h':
        default:
            break;
        }
    }

    return help(basename(argv[0]));
}

int main (int argc, char *argv[])
{
    return menu (argc, argv);
}

//Written by Aloento.

关于为什么main函数只有一行
因为我们老师的要求是main函数不得超过5行
我不是很能理解他的脑回路
所以我就尝试着让他也不能理解我的脑回路(?

关于欧拉筛的注释都在上一篇文章了,这里就不重复放了
这个算法有个大问题就是每次都要从0算起,无论你要求的起始点在哪
但是看在它线性时间复杂度的面子上就不再造轮子了

关于为什么不能从其他数字开始算起
这和欧拉筛法的原理有关系
这个算法其实默认认为前几个数字是素数
也就是说23这么个数一定是素数
在这个基础上往下计算
所以你如果从半中央开始算的话还得重新思考一下算法
有哪位大佬写出来的记得给我说一声我好去膜拜

算一亿位只要半秒我个人觉得还行
再大的数字在Windows上会崩溃,得在Linux上跑
那个判断起始点的if段写的也不好,不过我就不拿空间换时间了
反正看的是筛选效率又不是打印效率(ε=ε=ε=┏(゜ロ゜;)┛

第二天:把if那段修了一下,不然晚上做噩梦(

主要的知识点除了欧拉筛以外还有:
getopt传参启动,atoi把char转int等
getopt的optarg很神奇,它会判断你是第几次请求
每请求一次就会指向下一个argv
我这里最开始被坑了一下

atoi等一系列操作在失败的时候只会返回0
这一点不是很好,得在最开始的时候判断一下是否是数字
关于为什么" 0123456789"里面零的前面有个空格
那是因为optarg传回的参数就带个空格在前面
但是如果你在后面加个空格,比如 -e 10 100
那个100就是下一个argv,所以不用担心出问题
要读取100,再请求一次optarg就好了

后面要是还想起啥就下一篇再说吧
最近在玩命学JavaFX,写这玩意的时候老是在想
我现在要是在写Java的话这个就简单了那个也轻松了
(而且还下意识的打了sysout

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值