Re: fgets problem
- From: Keith Thompson <kst-u@xxxxxxx>
- Date: Mon, 22 Dec 2008 14:49:54 -0800
Alan Peake <adpeake@xxxxxxxxxxxxxxxxxxxxxxxxx> writes:
I've been trying to read a text file into an array without much
success. The following is part of "main" and all appears OK until the
statement while (fgets(str,20,fp) !=NULL)
Sometimes it works fine and the file xtl.dat (argv[1]) is read in
perfectly and the program performs as expected. But more often than
not, it appears to treat the first line of xtl.dat (which is "0.51400)
as NULL and skips the rest of the file.
Can anyone see what I've done wrong?
Thanks
Alan
#include "stdio.h"
#include <math.h>
#include <stdlib.h>
float f[140] ;
main(argc,argv)
int argc ;
char *argv[] ;
{
FILE *fopen() , *fp ;
float freq=20.0,tol=0.0005 ;
float freqin(),tolin() ;
char *str,c ;
int i=0,j,k,size=120 ;
if ((fp=fopen(argv[1],"r")) == NULL) {
printf("No crystal list file %s\n",argv[1]) ; exit(1) ;
}
while (fgets(str,20,fp) != NULL) {
f[i]=atof(str) ;
for (i=0;i<130;i++) {
fgets(str,20,fp) ;
f[i] = atof(str) ;
printf(" %10s %3.6f %d",str,f[i],i) ;
}
fclose(fp) ;
The code you posted is incomplete; you're missing closing braces for
the while loop and for the main function. Judging by the indentation,
you call fopen() exactly once, but you call fclose() on each iteration
of the while loop. Calling fgets() on a closed file invokes undefined
behavior. I suspect that's the cause of your problem, but it's hard
to be sure without seeing your input.
There are a number of other things you should fix; some of them are
errors, some are style issues.
Include directives for standard headers should use <>, not "".
Change
#include "stdio.h"
to
#include <stdio.h>
You don't use anything from <math.h>, so that header isn't necessary.
This might be an artifact of the way you've trimmed the program for
posting (thank you for that).
Your array "f" is used only inside main, so there's no reason to
declare it at file scope. Again, this might be an artifact of the way
you've trimmed the program for posting, but it might still make more
sense to declare it in one function and pass a pointer to other
functions that use it.
I personally dislike putting a space in front of each semicolon, and I
always put a space after each comma. Not all C programmers share this
particular opinion, but I think most do.
Your declaration of main is an old-style declaration; there's no
longer any good reason to use such declarations. Use:
int main(int argc, char *argv[])
(I personally prefer "char **argv", but "char *argv[]" is certainly
valid.)
There's no need to re-declare fopen, and in fact it's a bad idea to do
so; <stdio.h> does that for you.
I find code that declares one thing per line to be clearer:
float freq = 20.0;
float tol = 0.0005;
It usually makes more sense to use double rather than float; it
usually provides more precision and range, and on many CPUs it's just
as fast.
You declare freqin() and tolin(), but you don't define or use them.
If they exist in your actual code, it would be better to provide
prototypes at file scope, probably in a header file. It's legal to
have function declarations inside a function definition, but it's
generally a bad idea.
exit(1) is, strictly speaking, not portable; use exit(EXIT_FAILURE)
unless you're sure that you specifically want to pass a status of 1 to
the calling environment.
130 is a "magic number"; there's nothing in your program that explains
why it has that value. Declare a constant, perhaps using #define.
In the loop, you call fgets() without checking the result. This is a
bad idea; you have no way of detecting failure. This makes your
program "brittle" in the presence of bad input data. You should also
think about what to do if an input line is longer than what your array
can hold.
Don't use the atof() function; it doesn't detect errors, and in fact
can invoke undefined behavior in some cases. (The exact circumstances
in which the behavior is undefined are not entirely clear, which is
another good reason not to use it.) Use strtod() instead; it's a
little more complicated, but the extra safety is well worth i.
All your output, other than the first line, is on a single line with
no '\n' characters. Was that your intent? Strictly speaking, if your
implementation requires a terminating '\n' at the end of the last line
of output, then failing to provide one can invoke undefined behavior
(though on most systems you'll just get a long line with no
end-of-line marker at the end) Perhaps you wanted:
printf(" %10s %3.6f %d\n", str, f[i], i);
--
Keith Thompson (The_Other_Keith) kst-u@xxxxxxx <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
.
- Follow-Ups:
- Re: fgets problem
- From: Alan Peake
- Re: fgets problem
- From: Eric Sosman
- Re: fgets problem
- References:
- fgets problem
- From: Alan Peake
- fgets problem
- Prev by Date: Re: fgets problem
- Next by Date: Re: fgets problem
- Previous by thread: Re: fgets problem
- Next by thread: Re: fgets problem
- Index(es):
Relevant Pages
|