Thread: Copying prime numbers into array

  1. #1
    Registered User
    Join Date
    Oct 2020
    Posts
    69

    Copying prime numbers into array

    I'm trying to implement a function that receives an array of integers and its capacity and fills the array with all the values read from the keyboard which are prime numbers, without overflowing it, and returns the number of elements copied into the array. It fills the values properly but doesn't stop when there are no more prime numbers to be copied and just fills the remaining positions with garbage values. Why is that?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <string.h>
    #define MAX 101
    unsigned checkNumber(char *word)
    {
        int i, len = strlen(word);
        for(i = 0; i < len; i++)
        {
            if(!isdigit(word[i]))
                return 0;
        }
        return 1;
    }
    unsigned isPrime(int n)
    {
        int i, m = n/2;
        for(i = 2; i <= m; i++)
        {
            if(n%i == 0)
            {
                return 0;
                break;
            }
        }
        return 1;
    }
    void countPrimes(char *s, int *arr, size_t cap)
    {
        int n, countPrimes = 0;
        while(fgets(s, MAX, stdin))
        {
            s[strlen(s)-1] = '\0';
            char *word = strtok(s, " ");
            while(word)
            {
                if(checkNumber(word))
                {
                    n = atoi(word);
                    //printf("Word : %s\n", word);
                    if(isPrime(n))
                    {
                            if(countPrimes < cap)
                            {
                                arr[countPrimes] = n;
                                countPrimes++;
                                cap -= countPrimes;
                            }
                            //countPrimes++;
                            //cap -= countPrimes;
                            //printf("Prime number : %d\n", n);
                    }
                    //break;
            }
                word = strtok(NULL, " ");
            }
        //printf("There are %d prime numbers on this line.\n", countPrimes);
        }
    }
    int main()
    {
        char s[MAX];
        int arr[10];
        countPrimes(s, arr, sizeof(arr)/sizeof(arr[0]));
        for(int i = 0; i < sizeof(arr)/(sizeof(arr[0])); i++)
        {
            printf("%d\n", arr[i]);
        }
        return 0;
    }
    Input:
    13 abcd 2 4 8 10 abc3 17 31
    Output:
    13
    2
    17
    31
    0
    0
    0
    0
    0
    0

    If it was an array of characters after if(countPrimes < cap) I would just write arr[countPrimes] = '\0', but being an array of integers how can I signal that the copying stops?

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Just return the number of primes you found.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <math.h>
     
    int checkNumber(const char *word)
    {
        for (int i = 0; word[i]; ++i)
            if (!isdigit(word[i]))
                return 0;
        return 1;
    }
     
    int isPrime(int n)
    {
        int sq = sqrt(n);
        for (int i = 2; i <= sq; ++i)
            if (n % i == 0)
                return 0;
        return 1;
    }
     
    int countPrimes(int *arr, int cap)
    {
        const char *const Seps = " \n";
        int nPrimes = 0;
        char s[1000];
        while (fgets(s, sizeof s, stdin))
        {
            const char *word = strtok(s, Seps);
            while (word)
            {
                if (checkNumber(word))
                {
                    int n = atoi(word);
                    if (isPrime(n))
                    {
                        if (nPrimes >= cap)
                        {
                            printf("Array capacity overflow\n");
                            return nPrimes;
                        }
                        arr[nPrimes++] = n;
                    }
                }
                word = strtok(NULL, Seps);
            }
        }
        return nPrimes;
    }
     
    int main()
    {
        int arr[10];
        int nPrimes = countPrimes(arr, sizeof arr / sizeof arr[0]);
        for (int i = 0; i < nPrimes; i++)
            printf("%d\n", arr[i]);
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Oct 2020
    Posts
    69
    Thank you! If I wanna work with dynamically allocated arrays is this the way to go?
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    #define MAX 100
    unsigned checkNumber(char* word)
    {
        int i, len = strlen(word);
        for(i = 0; i < len; i++)
        {
            if(!isdigit(word[i]))
                return 0;
        }
        return 1;
    }
    int isPrime(int n)
    {
        int i, m = n/2;
        for(i = 2; i <= m; i++)
        {
            if(n%i == 0)
            {
                return 0;
                break;
            }
        }
        return 1;
    }
    char** copyOfPrimes()
    {
        char** primes = NULL;
        int countPrimes = 0;
        char buf[MAX];
        while(fgets(buf, MAX, stdin))
        {
            buf[strlen(buf)-1] = '\0';
            char *word = strtok(buf, " ");
            while(word)
            {
                if(checkNumber(word))
                {
                    int n = atoi(word);
                    if(isPrime(n))
                    {
                        char *copy = strdup(word);
                        if(!copy)
                        {
                            printf("Error copying word.\n");
                            return NULL;
                        }
                        char** auxPrimes = realloc(primes,(countPrimes+1)*sizeof(char*));
                        if(!auxPrimes)
                        {
                            printf("Error reallocating memory.\n");
                            free(primes);
                            return NULL;
                        }
                        primes = auxPrimes;
                        primes[countPrimes] = copy;
                        countPrimes++;
                    }
                }
                word = strtok(NULL, " ");
            }
        }
        char** aux = realloc(primes, (countPrimes+1)*sizeof(char*));
        if(aux)
        {
            primes = aux;
            primes[countPrimes] = NULL;
        }
        return primes;
    }
    int main(int argc, char* argv[])
    {
        char** arr = copyOfPrimes();
        int i = 0, nPrimes = 0;
        printf("The primes are:\n");
        for(i = 0; arr[i] != NULL; i++)
        {
            nPrimes++;
            printf("%s\n", arr[i]);
        }
        printf("There are %d prime numbers in total\n", nPrimes);
        return 0;
    }
    The output is the desired one, everything is working nice I just wanna make sure that I didn't do anything stupid or write extra code. Also, I believe working with dynamic allocation is more correct since I'm not given the exact capacity in the problem statement right?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 03-16-2012, 02:07 AM
  2. Replies: 1
    Last Post: 11-04-2011, 01:16 PM
  3. Replies: 7
    Last Post: 11-04-2011, 11:08 AM
  4. Replies: 12
    Last Post: 10-27-2011, 11:25 AM
  5. Prime Numbers and Array...
    By Deux in forum C Programming
    Replies: 12
    Last Post: 12-20-2004, 04:12 PM

Tags for this Thread