3 Replies - 830 Views - Last Post: 13 April 2010 - 10:29 PM Rate Topic: -----

#1 David W   User is offline

  • DIC supporter
  • member icon

Reputation: 298
  • View blog
  • Posts: 1,839
  • Joined: 20-September 08

find min, max, avg, of dynamic array

Posted 14 October 2008 - 06:38 AM

Description: See program / comments ...

You might like to note the input data validation and the C++ vector emulation ( Cvec )simple demo of a basic problem:
Find the minimum, maximum and average of an array of numbers ... 1. a dynamic array of doubles that is allocated accorded to user input ... 2. a 'C vector' using push_back ...
/*
    1.  C program to find minimum, maximum, average ... of a dynamic
        array of doubles.  (Note the 2 input validation loops.)
    
    http://developers-heaven.net/forum/index.php/topic,46.0.html
*/

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

#define HEADER "C program to find minimum, maximum, average " 
               "of a dynamic array of doubles ...n"

void getInfoRe(double* dAry, int size, double* min, double* max, double* avg);

int main()
{
    int i, numObservations; /* i is used below as an index counter ... */
    double* dAry; /* a pointer variable to hold an address of a double */
    double max, min, avg; /* variables to hold info returned by 'ref' */

    puts( HEADER );
    for( ; ; ) /* a C forever loop ... until break ... */
    {
        int numGoodVars;
        printf( "Please enter the number of observations: " );
        numGoodVars = scanf( "%d", &numObservations );
        while( getchar() != 'n' ) ; /* flush stdin ... */
        if( numGoodVars != 1 || numObservations < 1 )
            puts( "Only int's > 0 allowed here ..." );
        else { putchar('n'); break; }
    }
    
    /* when we reach here, we have a good 'int' above ... so get new memory */
    dAry = (double*) malloc( sizeof(double) * numObservations );
    if( dAry == NULL )
    {
        fputs( "Error: malloc failed to allocate memory. "
               "Press 'Enter' to exit ... ", stderr );
        getchar();
        exit(1);
    }

    /* dAry holds the address of the start of memory to hold numObservations */
    for( i = 0; i < numObservations ; ) /* i updated below ONLY if good data */
    {
        int numGoodVars;
        printf( "Observation %-3d : ", i+1 );
        numGoodVars = scanf( "%lf", &dAry[i] ); /* recall dAry holds 'double's */
        while( getchar() != 'n' ) ; /* flush all char's in stdin stream */ ;
        if( numGoodVars != 1 ) puts( "Numbers only please ..." );
        else ++i; /* since good data was obtained above ... now update i */
    }

    puts( "nYou entered ...n" );
    for( i = 0; i < numObservations; ++i )
    {
        printf( "%-3d : ", i+1 ); /* left justify in a 3 char wide field */
        printf( "%fn", dAry[i] ); /* Note: 'f' here handles double and float */
    }

    /* Note 1: dAry below is already an 'address' to the array of doubles */
    /* Note 2: 'addresses' are passed here ... to receiving pointer variables */
    getInfoRe( dAry, numObservations, &min, &max, &avg );

    printf( "nMin: %f  Max: %f  Average: %fn", min, max, avg );

    fputs( "nPress 'Enter' to continue ... ", stdout );
    getchar();
    return 0;
}

/* note where we are catching 'addresses' .... and note inside ... */
/* we have to use (i.e. dereference) the value at that address by using *var  */
void getInfoRe(double* dAry, int size, double* min, double* max, double* avg)
{
    int i;
    double sum = *min = *max = dAry[0]; /* to start, use this actual value */
    for( i = 1; i <size; ++i ) /* start at 1 since already used 0 above */
    {
        sum += dAry[i]; /* sum = sum + dAry[i] */
        if( dAry[i] < *min ) *min = dAry[i]; /* update ... if applies */
        if( dAry[i] > *max ) *max = dAry[i];
    }
    /* when we reach ... we have max, min and sum ... So can find average */
    *avg = sum/size; /*  Note:  double/int ... yields a double */
}



/*
    2.  C program to find minimum, maximum, average ... of a 'C vector' style
        dynamic array of doubles. (Note the input validation for each double.)
    
    http://developers-heaven.net/forum/index.php/topic,46.0.html
*/

/* Cvect.h */ /* this version 2010-04-14 */

#ifndef dw1CVECTOR_H
#define dw1CVECTOR_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* re. memcpy */

#define CHUNK_SIZE 5 /* increase/re-set this to match your data size */

typedef struct myDat
{
    double val;
} Dat ;

typedef struct myCvec
{
    Dat* ary;
    int size;
    int cap; /* capacity */
} Cvec ;

void init( Cvec* );
void push_back( Cvec* ad, Dat* d );
void resize( Cvec* ad );
void freeAll( Cvec* ad );
void myAssert( int condition, char text[] );

void init( Cvec* ad )
{
    ad->ary = NULL;
    ad->size = ad->cap = 0;
}

void push_back( Cvec* ad, Dat* d )
{
    if( ad->size == ad->cap ) resize( ad );
    /* now add in new dat ... */
    memcpy( &(ad->ary[ad->size]), d, sizeof(Dat) );
    ++ ad->size;
}

/* new array to hold one 'chunk' more records than before, copies old to new */
void resize( Cvec* ad )
{
    Dat* p;
    ad->cap += CHUNK_SIZE;
    p = (Dat*) realloc( ad->ary, ad->cap * sizeof(Dat) );
    if( p == NULL )
    {
        freeAll( ad );
        myAssert( 0, "Error: calloc failed to allocate memory." );
    }
    /* else ... */
    ad->ary = p; /* update ... the base address of our ad->ary ... */
}

void freeAll( Cvec* ad )
{
    if( ad->ary == NULL ) return;
    /*
    int i;
    for( i = ad->size-1; i >= 0; --i )
    {
        free(...); // pointer to any dynamic memory in struct myDat
        ...
        free(...);
    }
    */
    free( ad->ary );
    ad->ary = NULL;
    ad->size = ad->cap = 0; /* update ... */
}

void myAssert( int condition, char text[] )
{
    if( !condition )
    {
        fprintf( stderr, "%sn", text );
        fputs( "Press 'Enter' to exit program ... ", stderr );
        getchar();
        exit(1);
    }
}

#endif



#define HEADER "C program to find minimum, maximum, average " 
               "of a 'C vector' of doubles ...n"
               
void getInfoRe( Cvec* ad,  double* min, double* max, double* avg );
int more( void );


int main( void ) /* ********************************************************* */
{
    int i = 0; /* i is used below as an index counter ... */
    double max, min, avg; /* variables to hold info returned by 'ref' */
    Cvec v;
    init( &v ); /* Note: MUST initial Cvec v ... for Cvec to work */
    
    puts( HEADER );
    for( ; ; )
    {
        Dat d;
        int numGoodVars;
        printf( "Observation %-3d: ", i+1 );
        numGoodVars = scanf( "%lf", &d.val );
        while( getchar() != 'n' ) ; /* flush all char's in stdin stream */ ;
        if( numGoodVars != 1 ) puts( "Numbers only please ..." );
        else
        {
            push_back( &v, &d ); /* since good data was obtained */
            if( !more() ) break;
            /* else ...*/
            ++i;
        }
    }

    puts( "n You entered ...n" );
    for( i = 0; i < v.size; ++i )
    {
        printf( "%-3d: ", i+1 ); /* left justify in a 3 char wide field */
        printf( "%fn", v.ary[i].val ); /* Note: 'f' here handles double and float */
    }

    /* Note: 'addresses' are passed here ... to receiving pointer variables */
    getInfoRe( &v, &min, &max, &avg );
    printf( "n Min: %f  Max: %f  Average: %fn", min, max, avg );
    
    printf( "n Before freeAll: v.size = %d, v.cap = %dn", v.size, v.cap );
    freeAll( &v );
    printf( "n After  freeAll: v.size = %d, v.cap = %dn", v.size, v.cap );
    
    fputs( "n Press 'Enter' to continue ... ", stdout );
    getchar();
    return 0;
} /* ************************************************************************ */


/* note where we are catching 'addresses' .... and note inside ... */
/* we have to use (i.e. dereference) the value at that address by using *var  */
void getInfoRe( Cvec* ad, double* min, double* max, double* avg )
{
    int i;
    double sum = *min = *max = ad->ary[0].val; /* to start, use this actual value */
    for( i = 1; i < ad->size; ++i ) /* start at 1 since already used 0 above */
    {
        sum += ad->ary[i].val;
        if( ad->ary[i].val < *min ) *min = ad->ary[i].val; /* update ... */
        if( ad->ary[i].val > *max ) *max = ad->ary[i].val;
    }
    /* when we reach ... we have max, min and sum ... So can find average */
    *avg = sum/ad->size; /*  Note:  double/int ... yields a double */
}

int more( void )
{
    int c, reply;
    fputs( "More (y/n) ? ", stdout );
    reply = c = getchar();
    while( c != 'n' ) c = getchar(); /* flush stdin ... */
    return !(reply=='n' || reply=='N');
}



Is This A Good Question/Topic? 0
  • +

Replies To: find min, max, avg, of dynamic array

#2 David W   User is offline

  • DIC supporter
  • member icon

Reputation: 298
  • View blog
  • Posts: 1,839
  • Joined: 20-September 08

Re: find min, max, avg, of dynamic array

Posted 05 March 2010 - 12:10 PM

Now with C++ vector push_back emulation in C ..
Was This Post Helpful? 0
  • +
  • -

#3 David W   User is offline

  • DIC supporter
  • member icon

Reputation: 298
  • View blog
  • Posts: 1,839
  • Joined: 20-September 08

Re: find min, max, avg, of dynamic array

Posted 10 April 2010 - 11:42 PM

You may like to also see this 'Cvec' of struct's example: http://www.dreaminco...snippet5142.htm
Was This Post Helpful? 0
  • +
  • -

#4 David W   User is offline

  • DIC supporter
  • member icon

Reputation: 298
  • View blog
  • Posts: 1,839
  • Joined: 20-September 08

Re: find min, max, avg, of dynamic array

Posted 13 April 2010 - 10:29 PM

Updates maintained at: http://developers-he...index.php/topic,106.msg356.html#msg356
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1