arrayscclasspointersminmax

dynamic array allocation, pointers, min, max, avg, sum


I have been trying to run this code and keep getting segmentation faults, but the array does print. What the heck am I doing wrong? I believe the problem is somewhere in main with the format of functions or with the parameters I am putting in the functions, I have tried so many ways but nothing I have tried seems to work.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


void fillArray(int arr[], int arr_size);
void printArray(int arr[], int arr_size);
void fMin(int arr[], int arr_size, int *q);
void fMax(int arr[], int arr_size, int *p);
void fSum(int arr[], int arr_size, int *x);


int main(int argc, char *argv[])
{
    int *arr=NULL;
    int arr_size = atoi(argv[1]);
    arr = malloc(arr_size * sizeof(int));

    if(argc <= 2)
    {
        printf("ERROR: invalid command line args");
        printf("Expecting: EXCECUTABLE <SIZE>");
    }

    fillArray(arr, arr_size);

    int i;
    for(i=0; i<arr_size; i++)
    {
        printf("argv[%d] - %2d", arr_size, arr[i]);
        printf("\n");
    }

    printArray(arr, arr_size);

    int *min, *max ,avg, sum;
    int *p;
    int *q;
    int *x;
    avg = sum / arr_size;

    fMax(arr, arr_size, p);
    fMin(arr, arr_size, q);
    fSum(arr, arr_size, &sum);

    printf("Max: %3d Pos: %3d \n", *max, *p);
    printf("Min: %3d Pos: %3d \n", *min, *q);
    printf("Sum: %3d \n", *x);
    printf("Avg: %3d \n", avg);

    //for realloc! printArray(arr, arr_size);

    free(arr);
    return 0;
}

void fillArray(int arr[], int arr_size)
{
     srand(time(NULL));
    int i;
    for(i=0; i<arr_size; i++)
    {
        arr[i] = rand() % 101;
    }
}//good!

void printArray(int arr[], int arr_size)
{
    int i = 0;
    printf(" POS | VAL \n");
    printf("-----------\n");
    for(i=0; i<arr_size; i++)
    {
         printf(" %3d | %3d \n", i, arr[i]);
     }
}//good!

void fMin(int arr[], int arr_size, int *q)
{
    int i;
    int *min=NULL;
    min=&arr[i];
    for(i=1; i<arr_size; i++)
    {
        if(arr[i] < *min)
        {
            min = &arr[i];
            q = &i;
        } 
    }
}//cant null pointer

void fMax(int arr[], int arr_size, int *p)
{
    int i;
    int *max=NULL;
    max = &arr[i];
        for(i=1; i<arr_size; i++)
        {
            if(arr[i] > *max)
            {
                max = &arr[i];
                p = &i;
            } 
        }
}//good?
void fSum(int arr[], int arr_size, int *x)
{
    int i;
    int sum = *x;
    for (i=0; i<arr_size; i++)
    {
        *x = i + arr[i];
    }
}//what  the  heckie goin on here

I run"./a.out 5 6"

and it outputs:

argv[5] - 31
argv[5] - 13
argv[5] - 27
argv[5] - 83
argv[5] - 23
 POS | VAL 
-----------
   0 |  31 
   1 |  13 
   2 |  27 
   3 |  83 
   4 |  23 
zsh: segmentation fault  ./a.out 5 6

Solution

  • The majority of your problems lie in the lines:

    int *min, *max, avg, sum;
    int *p;
    int *q;
    int *x;
    avg = sum / arr_size;
    
    fMax(arr, arr_size, p);
    fMin(arr, arr_size, q);
    fSum(arr, arr_size, &sum);
    

    You pass the uninitialized pointers p and q to fMax() and fMin(); that's a recipe for crashing. You calculate the average before calculating the sum (so sum is uninitialized).

    You need code more like:

    int min, max, avg, sum;
    
    fMax(arr, arr_size, &max);
    fMin(arr, arr_size, &min);
    fSum(arr, arr_size, &sum);
    avg = sum / arr_size;
    

    I've not checked the functions, but the calls were definitely bogus.

    […time passeth…]

    There are problems in the functions too. For example, in fMin(), it isn't entirely clear whether you are passing back the index of the minimum value or the actual minimum value, but there are problems galore.

    You have:

    void fMin(int arr[], int arr_size, int *q)
    {
        int i;
        int *min=NULL;
        min=&arr[i];
        for(i=1; i<arr_size; i++)
        {
            if(arr[i] < *min)
            {
                min = &arr[i];
                q = &i;
            } 
        }
    }
    

    The line min = &arr[i]; uses an uninitialized variable, i, to index into the array. Local variables in C are not magically initialized to zero! There's no point in initializing min to NULL and immediately setting it to something else. You could use:

    int *min = &arr[0];
    

    Theoretically, you should check that arr_size is bigger than zero before doing that.

    Your assignment q = &i; means you can no longer relay any information back to the calling code — you've lost the pointer to the variable in the calling function.

    You should probably use code more like this (where you'd need to include <limits.h> to get INT_MAX):

    void fMin(int arr[], int arr_size, int *pmin)
    {
        if (arr_size <= 0)
        {
            *pmin = INT_MAX;
            return;
        }
        int min = arr[0];
        for (int i = 1; i < arr_size; i++)
        {
            if (arr[i] < min)
                min = arr[i];
        }
        *pmin = min;
    }
    

    This returns the minimum value. If you want the index of the first element containing the minimum value, you change the code a bit:

    void fMin(int arr[], int arr_size, int *pmin)
    {
        if (arr_size <= 0)
        {
            *pmin = INT_MAX;
            return;
        }
        int min = arr[0];
        int idx = 0;
        for (int i = 1; i < arr_size; i++)
        {
            if (arr[i] < min)
            {
                min = arr[i];
                idx = i;
            }
        }
        *pmin = idx;
    }
    

    If you want the index of the last entry containing the minimum value, you change the test to if (arr[i] <= min). Another sensible change would have the function return the minimum value, or the index of the minimum value, instead of taking a pointer to hold the return value.

    There are analogous problems with fMax().

    The code in fSum() should probably be like this:

    int fSum(int arr[], int arr_size)
    {
        int sum = 0;
        for (int i = 0; i < arr_size; i++)
            sum += arr[i];
        return sum;
    }
    

    Here I've changed the code to return the result. Note that this is vulnerable to arithmetic overflow, which leads to undefined behaviour. However, you're probably not going to run into that as a problem.