You are faced with the classic case of "How do I read an unknown number of X?". The answer is simply allocate some initial number of elements with malloc (or calloc or realloc) and keep track of what you have allocated and then the number of elements used (filled). When used == allocated, you realloc the array and increase the number of elements available by some amount, either some fixed amount each time or some multiple of the current. Doubling the number of elements is a fairly good balance of allocation growth and the number of reallocations required.
A simple example reading an unknown number of doubles with scanf and then outputting the number read and the sum could be:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
size_t used = 0, allocated = 2; /* used doubles/allocated doubles */
double *arr, sum = 0.0; /* array & sum of elements */
/* allocate initial 'allocated' number of doubles */
if (!(arr = malloc (allocated * sizeof *arr))) {
perror ("malloc-arr");
return 1;
}
while (scanf ("%lf", &arr[used]) == 1) { /* read doubles until EOF */
sum += arr[used++]; /* add to sum, increment used */
if (used == allocated) { /* if used == allocated */
/* reallocate more doubles using a temporary pointer */
void *tmp = realloc (arr, 2 * allocated * sizeof *arr);
if (!tmp) { /* validate reallocation */
perror ("realloc-tmp");
break; /* don't exit, original arr still good, break */
}
arr = tmp; /* assign reallocated block to arr */
allocated *= 2; /* update number allocated */
}
}
printf ("%zu doubles entered with sum: %.2f\n", used, sum);
free (arr); /* free the memory you have allocated */
}
(note: you ALWAYS realloc to a temporary pointer because if realloc fails, it will return NULL overwriting your original pointer address preventing you from ever being able to access or free() the original block resulting in a *memory leak*. Ifrealloc` does fail, by using a temporary pointer, your existing data is preserved through the original pointer)
You can now pass arr and the number of elements it holds (used) to any function that needs that information.
Example Use/Output
$ ./bin/sumdoubles
1.1
2.2
3.3
4.4
5.5
6.6
7.7
8.8
9.9
9 doubles entered with sum: 49.50
or redirect 10,000 floating-point values from a file:
$ ./bin/sumdoubles < ../dat/10000float.txt
10000 doubles entered with sum: 117991733.64
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to ensure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/sumdoubles
==6316== Memcheck, a memory error detector
==6316== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6316== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6316== Command: ./bin/sumdoubles
==6316==
1.1
2.2
3.3
4.4
5.5
6.6
7.7
8.8
9.9
9 doubles entered with sum: 49.50
==6316==
==6316== HEAP SUMMARY:
==6316== in use at exit: 0 bytes in 0 blocks
==6316== total heap usage: 6 allocs, 6 frees, 2,288 bytes allocated
==6316==
==6316== All heap blocks were freed -- no leaks are possible
==6316==
==6316== For counts of detected and suppressed errors, rerun with: -v
==6316== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Edit - Additional Problems In Your Functions
In
for(i = 0; i < sizeof(array); i++)
sizeof(array) is simply sizeof(a_pointer). An array is converted to a pointer on access. See: C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3). You would want to pass both the pointer and the number of elements, e.g.
double sums(double *array, size_t n)
{
size_t i;
double sumNum = 0;
for(i = 0; i < n; i++){
sumNum = sumNum + array[i];
}
return sumNum;
}
You would call sums in your main() as
size_t sum = sums (arr, used);
An example using a sums function (slightly modified to taste):
#include <stdio.h>
#include <stdlib.h>
double sums (double *array, size_t n)
{
double sumNum = 0;
for (size_t i = 0; i < n; i++)
sumNum = sumNum + array[i];
return sumNum;
}
int main (void) {
size_t used = 0, allocated = 2; /* used doubles/allocated doubles */
double *arr, sum = 0.0; /* array & sum of elements */
/* allocate initial 'allocated' number of doubles */
if (!(arr = malloc (allocated * sizeof *arr))) {
perror ("malloc-arr");
return 1;
}
while (scanf ("%lf", &arr[used]) == 1) { /* read doubles until EOF */
if (++used == allocated) { /* if used == allocated */
/* reallocate more doubles using a temporary pointer */
void *tmp = realloc (arr, 2 * allocated * sizeof *arr);
if (!tmp) { /* validate reallocation */
perror ("realloc-tmp");
break; /* don't exit, original arr still good, break */
}
arr = tmp; /* assign reallocated block to arr */
allocated *= 2; /* update number allocated */
}
}
sum = sums (arr, used); /* call functions here */
printf ("%zu doubles entered with sum: %.2f\n", used, sum);
free (arr); /* free the memory you have allocated */
}
(output would be the same)
Look things over and let me know if you have any further questions.
mallocandrealloc. Makearra pointer to double (e.g.double *arr;), allocate some initial number of doubles (e.g.size_t allocated = 2;) and then arrayarr = malloc (allocated * sizeof *arr);(validate the allocation), then start adding doubles toarr, keep a counterused, whenused == allocated, double the number allocated with,void *tmp = realloc (arr, 2 * allocated * sizeof *arr);now validatetmp, and if good,arr = tmp;andused *= 2;and keep going, rinse and repeat.