1

I am making a program that finds all of the products of two prime numbers within a given range and prints them out. The program works fine with having the numbers print if I check them normally in each child process. The problem comes about when I try to write the number to the pipe instead of just printing it. I honestly have been working on this for days now and getting nowhere.

Below, I have posted the working code that prints out the products of two primes. I have the write to the pipe commented out as well as the read. Please let me know if you can help me out!

/*
progname 4 2 1000, should create 4 child processes that will find 
the product of two primes between 2 and 1000 and print them to the screen.
*/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
int strtoi(char* str);
void findProductsOfTwoPrimes(int numChildren, int rangeMin, int rangeMax);
void printArray(int* array, int size);
int isSemiprime(int number);

int fd[2];

int main(int argc, char* argv[]) {


    /*________________________________ 
    |   -------- Parameters --------  |
    | argv[0]: progname               |
    | argv[1]: number children (int)  |
    | argv[2]: range min (int)        |
    | argv[3]: range max (int)        |
    |_________________________________|*/
    int numChildren, rangeMin, rangeMax;

    switch (argc) {

        case 2:
            printf("%s", "Provide Range\nInvalid Usage: progname numChildren(int) rangeMin(int) rangeMax(int)\n");
            break;

        case 3:
            printf("%s", "Provide Range Max\nInvalid Usage: progname numChildren(int) rangeMin(int) rangeMax(int)\n");
            break;

        case 4:

            /*Retrieve values from argument array*/
            numChildren = strtoi(argv[1]);
            rangeMin = strtoi(argv[2]);
            rangeMax = strtoi(argv[3]);

            pipe(fd);

            findProductsOfTwoPrimes(numChildren, rangeMin, rangeMax);

            break;

        default:
            printf("%s", "Invalid Usage: progname numChildren(int) rangeMin(int) rangeMax(int)\n");
            break;
    };

    exit(0);
}

/*_________________________________________________
| This function converts a char* to an integer if  |
| possible.                                        |
|__________________________________________________|*/
int strtoi(char* str) {

    /* set errno  & escape check var*/
    errno = 0;
    char* p;

    /* attemp conversion to long */
    long longVal = strtol(str, &p, 10);


    if (*p != '\0' || errno != 0) {
        /*print error*/
        printf("%s", "Please provide correct usage: progname numChildren(int) rangeMin(int) rangeMax(int)\n");
        return -1;
    }


    /* check if long is in range of int */
    if (longVal < INT_MIN || longVal > INT_MAX) {
        return -1;
    }

    int intVal = longVal;

    return intVal;
}

void findProductsOfTwoPrimes(int numChildren, int rangeMin, int rangeMax) {
    
    int readResult;

    /* if we have valid range */
    if ((rangeMax - rangeMin) > 0) {
    
        /* get size from input range*/
        int size = rangeMax - rangeMin + 1;

        /* allocate space for an array */
        int* numbers = malloc(size * sizeof(*numbers));
        if (!numbers) {
            printf("%s", "Error allocating memory\n");
        }

        /* fill array */
        int i;
        for (i = 0; i < size; i++) {
            numbers[i] = i + rangeMin;
        }

        /*printArray(numbers, size); debugging*/ 

        /* see if we are evenly divisable */
        int childrenEvenlyFit;
        if (size % numChildren == 0) {
            childrenEvenlyFit = 1;
        }
        else {
            childrenEvenlyFit = 0;
        }

        if (childrenEvenlyFit == 1) {

            /* define fork variables */
            int j, pid = 1, childCount = 0;

            /* get the number of elements each child is responsible for */
            int ourPortionSize = size / numChildren;

            close(fd[0]);

            for (j = 0; j < numChildren; j++) {

                if (pid != 0) {
                    childCount++;

                    pid = fork();

                    if (pid == 0) { /* we are a child */

                        /* we have to use childCount to see where in the array we are checking */
                        /* array starts at 0, ends at size */
                        /* childCount starts at 0, ends at numChildren */

                        /* printf("child %d \n", childCount); debugging */

                        /* get the range of elements respective to portion size and childCount */
                        int rangeMax = (childCount * ourPortionSize) - 1;
                        int rangeMin = (childCount * ourPortionSize) - ourPortionSize;

                        int k;
                        for (k = rangeMin; k <= rangeMax; k++) {
                            if (isSemiprime(numbers[k])) {
                                printf("%d\n", numbers[k]);
                                //write(fd[1], &numbers[k], sizeof(numbers[k]));
                            }
                        }
                        
                    }
                }

            }

            //read(fd[0], &readResult, sizeof(readResult));
            //printf("Result: %d\n", readResult);


        }
        else {
            printf("%s", "Provide child number that goes evenly into range...\n");
        }

        /* deallocate array */
        free(numbers);
    }
    else {
        printf("%s", "Invalid Range\n");
    }


}

/*_________________________________________________
| This function prints a given array with an input |
| integer size                                     |
|__________________________________________________|*/
void printArray(int* array, int size) {

    printf("[");

    int i;
    for (i = 0; i < size - 1; i++) {
        printf("%i, ", array[i]);
    }

    if (size >= 1) printf("%i", array[size - 1]);

    printf("]\n");
}


/*_________________________________________________
| This function checks if an integer is semiprime  |
|__________________________________________________|*/
int isSemiprime(int number) {

    int count = 0;
    int i;
    for (i = 2; count < 2 && i * i <= number; i++) {
        while (number % i == 0) {
            number /= i, ++count;
        }
    }

    if (number > 1) {
        ++count;
    }

    /* returns 1 if semiprime, 0 if not */
    return count == 2;
}
Karlee
  • 11
  • 1
  • Does this answer your question? [How to send a simple string between two programs using pipes?](https://stackoverflow.com/questions/2784500/how-to-send-a-simple-string-between-two-programs-using-pipes) – user14063792468 Mar 26 '21 at 15:06

0 Answers0