Question:
Question for C programming?
Outsider J
2012-03-29 22:04:14 UTC
Exercise 1. Write a program to calculate the average for an arbitrary number of floating-point values that are entered from the keyboard. Store all values in memory that’s allocated dynamically before calculating and displaying the average. The user shouldn’t be required to specify in advance how many values there will be. How can I let the user all the number he wants and how would the program know if the user is finished entering values so the program could compute for the average.

Now, I'm a beginner at programming and I don't have full knowledge about pointers. My problem in this one is the part that the user shouldn't be required on the number of values, and the number of values can't also be specified beforehand.
Five answers:
Jonathan
2012-03-30 00:45:13 UTC
You will need to learn about pointers to achieve the task. The following code permits the entry of numbers, as many per line as desired, as many lines as desired, using spaces to separate them on any one line. A blank line (one that only has blanks or nothing at all) terminates the input. The code uses malloc() and realloc() and includes an algorithm to increase the size of the temporary array rapidly at first (greedy.) But it switches to a more miserly approach when the greedy approach fails once. This lets it reach pretty much all of the available memory, if needed. At that point, it just frees everything up and fails.



#include

#include

#include

#define getline(a) fgets( (a), sizeof( (a) ), stdin )

double * readvector( unsigned int * n ) {

    char s[200], *e, *f, *z;

    double v, *a;

    unsigned int i, size, extend;

    enum { greedy, miserly } mode;

        mode= greedy;

        size= extend= 128;

        if ( (a= (double *) malloc( sizeof(double)*size )) == NULL )

            return NULL;

        for ( i= size= 0, z= getline( s ); z != NULL; z= getline( s ) ) {

            for ( e= s; *e != '\0'; ++e )

                if ( !isspace( *e ) && *e != '\n' && *e != '\r' )

                    break;

            if ( *e == '\0' )

                break;

            for ( v= strtod( e, &f ); e != f; v= strtod( e= f, &f ) ) {

                while ( i >= size && extend > 0 ) {

                    double *b= (double *) realloc( a, sizeof(double)*(size+extend) );

                    if ( b != NULL ) {

                        a= b;

                        size += extend;

                        if ( mode == greedy )

                            extend= size;

                        break;

                    }

                    mode= miserly;

                    extend >>= 1;

                }

                if ( i >= size ) {

                    free( a );

                    return NULL;

                }

                a[i++]= v;

            }

        }

    return (double *) realloc( a, sizeof(double)*(*n= i) );

}

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

    unsigned int n;

    double *v;

        printf( "Enter any number of lines of space-separated values."

                  " Blank line terminates:\n" );

        v= readvector( &n );

        if ( v != NULL && n > 0 ) {

            unsigned int i;

            double sum= v[0];

            for ( i= 1; i < n; ++i )

                sum += v[i];

            printf( "N = %u, Average = %lf\n", n, sum / (double) n );

            free( v );

        }

    return 0;

}
husoski
2012-03-29 22:41:49 UTC
If the user does not specify the number of values in advance, you can't allocated the array accurately in advance. You have to guess at the allocation. If that turns out to be too small, then you have to be able to reallocate the array without losing the original data.



Two tools from the Standard C Library help here: malloc and realloc(), plus a third: free() to be used when the array is no longer needed.



... declarations:



double *pvalues = NULL;

int max_values;

int values_used;



... in your init code:



max_values = 100;

pvalues = (double*) malloc(max_values * sizeof(double));

if (pvalues == NULL) { print error and die...not enough memory }

values_used = 0;



...after reading a double named new_value that needs to be stored in the array:



if (values_used >= max_values) /* if the array is full */

{

max_values = 2*max_values; /* double array size */

double *newptr = (double*) realloc(pvalues, max_values*sizeof(double));

if (newptr == NULL) { print error and die ... not enough memory }

}

pvalues = newptr;

pvalues[values_used++] = new_value;



...at the end of the program:



/* free the data buffer, if it's been allocated */

if (pvalues != NULL) free(pvalues);



That pattern: "add to the array until it fills up, then reallocate to a larger size when it fills up" is used a lot, especially in C where you have to write a lot of your own data structure handling. In C++ you have a vector<> type that does all of this, and a bit more, for you. Ditto for Java's ArrayList<>, also found in C#.



Note that no copying is necessary when using realloc(). realloc() does that for you, either by excpanding the current allocation in place, or by a new malloc() and copying the data. If a new memory block is allocated, the old is freed after copying the data.



The reason for newptr is to get into the habit of NOT overwriting the pointer you are trying to reallocate until you verify that return from realloc() is not NULL. If the reallocation fails, realloc() dos not free the old memory. In this exercise, you don't need to worry about recovery. Just print a message and return a nonzero value. If the recovery action is to not halt the program, you need to remember the original array address so you can reuse it or free it.



Everything you need should be in
MichaelInScarborough
2012-03-30 02:02:17 UTC
Hi, I suggest the following commented code and I hope this is helpful.

calloc is allocating memory and initializes the memory, realloc reserves

memory using the content of the buffer, adds additional memory and

returns a pointer to the reallocated memory address.



#include

#include

#include



/*I suggest the following:

1. Choose an arbitrary value, sufficiently big

to cover the needs of the user and initialize

a pointer with this:

*/

//arbitrary length of double array

// I made this value small, so that the realloc will be used at least once in the ideone scenario

const int iInit = 3;

int main()

{

// double array to store float values

double *dblNumber = calloc(3, sizeof(double));

// sum of dblNumbers

double dblSum = 0.0;

// continue number input y/n

char cAnswer = 'y';



//2. You need to have a counter, keeping track of

//the users inputs.

int iCounter = 0;

// 3. You need to request and tally the user's input:

while (1){

++iCounter;

// Boundary of currently allocated memory is reached

if (iCounter % iInit == 0) {

// we are allocating additional memory in the size of iInit * sizeof(double)

dblNumber = (double *)realloc(dblNumber, (iCounter + iInit) * sizeof(double));

}

printf("\nEnter a float> ");

(void)scanf("%lf", &dblNumber[iCounter]);

// Usually we terminate the user input with

// the enter key. This translates to '\n'. If

// we don't "flush" this '\n' away, it will

// automatically be stored in cAnswer.

// So we are moving the filepointer behind

// the '\n' and read from there ...

while(getchar() != '\n');

dblSum += dblNumber[iCounter];

printf("\nContinue? (y/n)> ");

(void)scanf("%c", &cAnswer);

// if the user enters explicitly n or N

// the average will be calculated from

// at least one number input by the user.

if (cAnswer == 'n' || cAnswer == 'N') {

break;

}

}

// Output the average

fprintf(stdout, "\nThe average of entered numbers is: %10.2lf", dblSum / iCounter);

// don't forget to release resources allocated!!!

free(dblNumber);

// EXIT_SUCCESS is defined in stdlib.h

return EXIT_SUCCESS;

}
hocking
2016-10-22 15:53:53 UTC
no longer anymore, at one time C++ replaced into in basic terms an extension of C. considering the fact that then, C has replaced, and so has C++. however that being said it really is no longer unusual for an same software to deliver jointly both C and C++. the tactic is an same, yet there are in basic terms some ameliorations int he libraries that you choose the compiler to link to.
anonymous
2012-03-29 22:17:12 UTC
dude, pay me

just kidding, seriosly there are scam operations that drag you along and make you pay them for this stuff. Stuff that I could blow their minds away with dude. go ahead pay them


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...