I find reading the fscanf documentation always helps. What it says to me is that it returns one of three values, (in your case.) One has to account for all three if one's programme is well-formed.
return |
meaning |
1 |
The parser was able to reasonably interpret and store the one value given, within the data type's limits. |
0 |
These bytes do not make sense given the format string. |
EOF |
the character couldn't be read for some other reason; it may be the end of the file. |
- To avoid duplicating the system of errors, perhaps
#include <errno.h>
would be efficient?
- I like to put related data in a structure,
struct { size_t count; double data[20]; } join;
one can query the size by const size_t join_max = sizeof join.data / sizeof *join.data;
.
- Be careful to test on the edge-case where there are 20 floats.
fopen
is an added complexity that shouldn't have to be there on simple command line programmes, the shell can usually do this nicer, ./a.out < data
.
- See this discussion on float vs double.
In your case, reading one double
might look like:
switch(scanf("%lf", &lf)) {
case EOF: if(feof(stdin)) goto eof; else goto catch;
case 0: errno = EILSEQ; goto catch;
case 1:
if(join.count < join_max) join.data[join.count++] = lf;
else { errno = ERANGE; goto catch; }
break;
}
--
"What's up with all the gotos?"
One at least has to account for these conditions:
- The result was added, try again.
- The file is finished, success.
- Read error, syntax error, or there is no space to hold more in the array; (depending on the application, I think these can be grouped together.)
It is easier if one has a standard out-of-band mechanism like exceptions. I can tell you how my code went, but this is just an quickly made up example, and not necessarily good design:
{
int success = EXIT_FAILURE;
(loop)
(scanf)
eof:
(print)
{ success = EXIT_SUCCESS; goto finally; }
catch:
sprintf(reason, "Data %lu", join.count);
perror(reason);
finally:
return success;
}