【问题标题】:C Sieve of Eratosthenes using ForkC 使用 Fork 筛选 Eratosthenes
【发布时间】:2022-02-03 08:29:42
【问题描述】:

我正在尝试在 C 中实现一个代码,它有一个文本文件作为输入,文本文件中的每一行都包含一个从 2 到 N 递增顺序的数字,我想使用埃拉托色尼筛法识别素数。我想为此使用 Fork()。

我找到了一种使用管道的方法,但我想知道是否有一种方法可以使用不带管道的 fork 来实现。

这是我的代码(我不是最好的,所以有点乱)

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>


//Delete multiples
void delete(int p, int r, int w){
    int i;
    while(read(r, &i, sizeof(i))){
        if(i % p != 0){
            write(w, &i, sizeof(i));
        }
    }
}

void primes(int r){
    int p;
    pid_t pid;
    
    if(read(r, &p, sizeof(p))){   
        int primePipe[2];
        pipe(primePipe);
        printf("%d\n", p); //Printing out the numbers
        
        pid = fork();
        if(pid < 0){ // Error with fork
            fprintf(stderr, "Fork Failed");
            exit(1);
        }else if(pid){   //Child
            close(primePipe[1]);
            primes(primePipe[0]);
        }else{   //Parent
            close(primePipe[0]);
            delete(p, r, primePipe[1]);
            close(primePipe[1]);
        }
    }
}
int main(int argc, char *argv[]) {
    int num;
    int pd[2];
    pid_t pid;
    pipe(pd); 
    char fileName[200];
    
    //Take a file as input
    printf("Enter the name of the file: \n");
    scanf("%s",fileName);
    FILE* file = fopen(fileName, "r");
         
    if (! file ){  
      printf("Error, the file cannot be read.\n"); 
      exit(-1); 
    } 
    
    pid = fork();
    if (pid < 0) { //Error with fork
      fprintf(stderr, "Fork Failed");
      exit(1);
      return 1;
    }else if(pid){ //Child
        close(pd[1]);
        primes(pd[0]);   
    }else{ //Parent 
        close(pd[0]);
        while (fscanf(file, "%d", & num) == 1 ){ //Going through the file
               write(pd[1], &num, sizeof(num)); 
        } 
        close(pd[1]);
    }

    exit(0);
}

【问题讨论】:

    标签: c pipe fork primes sieve-of-eratosthenes


    【解决方案1】:

    有很多方法可以进行进程间通信,但我认为管道对于您的目的可能是最简单的,我认为这只是一个学习练习(为您找到的每个素数分叉一个新进程总是要多得多比读取和写入管道的开销更大)。


    附录。这不是埃拉托色尼的筛子。除了加法和比较之外,您不需要任何算术运算(使用 % 运算符的埃拉托色尼筛子的任何实现都是错误的)。

    编辑

    原来的筛子算法是这样工作的:

    1. 取列表中的第一个数字,称为 n。有另一个最初设置为 n 的数字 c。将 n 记录为素数
    2. 从列表中删除 c。
    3. 将 n 添加到 c
    4. 如果 c 小于列表中的最大数,则返回步骤 2
    5. 如果您没有跑出列表末尾,请转到第 1 步。

    您需要为您的程序稍微修改算法。需要这样的东西(未经测试甚至编译)。

    void delete(int p, int r, int w)
    {
        int i;
        int c = p + p;
        while(read(r, &i, sizeof(i)))
        {
            if(i < c)
            {
                write(w, &i, sizeof(i));
            }
            else 
            {
                c = c + p;
            }
        }
    }
    

    【讨论】:

    • 谢谢你让我知道。您能否举例说明如何将 % 运算符的使用更改为适当的 Eratosthenes 筛?
    • @PsychoBunnies 在关于算法的答案中添加了一些内容。
    • 我明白了,我运行了它,但这让它在几个数字后停止。例如,我有一个高达 50 的测试文件,不幸的是它只会打印 2 3 5
    • @PsychoBunnies 正如我所说:未经测试。您可能需要进行一些调试。
    • 是的,我很难调试它以使其工作:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多