File Read help reqd

N

Naren

Hello All,

Can any one help me in this file read problem.

#include <stdio.h>



int main()
{
FILE* fp = fopen("TITLE.mx2","rb");

char h[100];

while(fscanf(fp,"%[^\r\n]",h) != EOF)
{
fprintf(stdout,"%s",h);
if((fscanf(fp,"%[\r\n]",h) == EOF)) //dummy
break;
}


fclose(fp);
return 0;

}

it goes into an infinite loop.

Am i eating up the EOF?

here while(fscanf(fp,"%[^\r\n]",h) != EOF)?

how to avoid it?

Thanks in advance.

Regards,
Naren.
 
C

CBFalconer

Naren said:
#include <stdio.h>
int main()
{
FILE* fp = fopen("TITLE.mx2","rb");
char h[100];

while(fscanf(fp,"%[^\r\n]",h) != EOF)

fscanf can never return EOF. Try reading its definition.
 
R

Robert Gamble

CBFalconer said:
Naren said:
#include <stdio.h>
int main()
{
FILE* fp = fopen("TITLE.mx2","rb");
char h[100];

while(fscanf(fp,"%[^\r\n]",h) != EOF)

fscanf can never return EOF. Try reading its definition.

According to my copy of the Standard:
7.19.6.2p16:

The fscanf function returns the value of the macro EOF if an input
failure occurs
before any conversion.

Am I missing something?

Robert Gamble
 
C

Chris Torek

Naren said:
FILE* fp = fopen("TITLE.mx2","rb");
char h[100];

while(fscanf(fp,"%[^\r\n]",h) != EOF) {
fprintf(stdout,"%s",h);
if((fscanf(fp,"%[\r\n]",h) == EOF)) //dummy
break;
}
... goes into an infinite loop.

One possibility is that the fopen() has failed and fp==NULL and
the undefined behavior of calling fscanf() with this NULL is
that it does nothing other than return a value not equal to -1.
For instance, perhaps your fscanf() happens to return 42 when
called with NULL (and read no data, or at least do nothing
visibly harmful). This could easily result in an infinite
loop.

Another possibility is that one of the fscanf() calls overruns the
buffer h[], i.e., there are more than 99 non-\r non-\n characters
in sequence at some point, or there are more than 99 \r-or-\n
characters in sequence at some other point. This would store
more than 100 "char"s in the 100-char array, leading to undefined
behavior, which could also result in an infinite loop.

It also seems very odd to open with "rb" and then use fgets(),
since fgets() is a "text-file-oriented" operation (text files are
composed of "lines", while binary files contain arbitrary binary
data not necessarily composed of lines). But this in and of
itself should not result in an infinite loop.

Other than these issues, the code *should* not loop forever. The
first fscanf() directive -- a "%[" -- matches one or more non-\r
non-\n characters, or fails with either an input or a matching
failure. In most cases (non-blank first text line), it will succeed,
and read-and-convert the non-\r-or-\n characters, storing them in
h[].

If the file begins with a sequence of \r-or-\n characters, the
first fscanf() performed will fail with a matching failure and
return 0, leaving garbage in the array h[]. The fprintf() to stdout
would then technically have undefined behavior, which theoretically
could result in an infinite loop; but in practical terms, on the
computer you are using (the one I see in my crystal ball :) ),
you would just get either garbage output, or no output at all, from
that fprintf().

Having either succeeded or failed with a matching failure, fscanf()
will then return either 1 or 0 (respectively). You ignore this
distinction in return values -- which is almost always a bug, and
is indeed a bug in this case -- and go on to print the contents of
the array (possibly garbage).

You then call fscanf() again, using another %[ directive, but this
one says "read and convert at least one, and as many as possible,
\r or \n characters". Since the previous conversion will have read
and converted everything that is not a \r or \n, the only possible
character in the stream at this point is \r or \n. Thus, if there
are any characters to read at all, the %[ directive will definitely
succeed. The only other possibility is that getc(fp) will return
EOF (due to input error or end-of-file), rather than returning a
'\r' or '\n' character; in that case, the fscanf() call itself will
return EOF, and the "break" will terminate the loop. Since the
loop does not terminate, we can assume that fscanf() does find at
least one \r or \n, and writes them into the array h[]. (Thus, if
there are 37 '\r' characters followed by 3 '\n's followed by 9
'\r's followed by 'x' or EOF, h[] will have 37+3+9+1 = 50 bytes
written into it.) The fscanf() call will then return 1 -- the
only possible return values are EOF and 1, in this case. Hence
the test fscanf(...)==EOF is sufficient, unlike the initial one in
the while loop.

If the fscanf() does return 1, we know that the fscanf() stopped
at either a non-\r non-\n character, or it encountered EOF. Thus,
subsequent trips through the while loop's test will have a return
value from fscanf() of either EOF or 1. Only the very first
fscanf() performed can return 0 (when the file begins with a
'\r' or '\n' character).

All of this may leave the original poster with the question of what
he *should* code, instead of the above; but no one can really answer
that, as he has not expressed a goal, merely a question about the
loop. I can make a guess here (that the goal is to remove all
'\n' and/or '\r' characters from a binary file), but it is just a
guess, and it seems a little unlikely.
 
C

CBFalconer

Robert said:
CBFalconer wrote:
.... snip ...


According to my copy of the Standard:
7.19.6.2p16:

The fscanf function returns the value of the macro EOF if an input
failure occurs before any conversion.

Am I missing something?

No, but I am. Thanks for the correction.
 
A

Alberto =?iso-8859-1?Q?Gim=E9nez?=

El Thu, 02 Jun 2005 10:19:36 GMT, CBFalconer escribió:
No, but I am. Thanks for the correction.

Not at all. It says *input failure* needed to return EOF. So, if a conversion
occurs ([^\r\n]) with no input failure, fscanf will not return EOF and
thus the while will be a forever loop. Please correct me if i'm wrong.

Greetings
 
W

Walter Roberson

El Thu, 02 Jun 2005 10:19:36 GMT, CBFalconer escribió:
Not at all. It says *input failure* needed to return EOF. So, if a conversion
occurs ([^\r\n]) with no input failure, fscanf will not return EOF and
thus the while will be a forever loop. Please correct me if i'm wrong.

No, if a conversion occurs then at least one character will be removed
from the input stream -- and with that particular format, all the
characters until EOF or the first \r or \n will be removed from the
input stream.

Thus after the execution of the fscanf() that is the condition of the
while() loop, if a conversion occured then input has been removed and
one is positioned at an EOF or \r or \n. Then one encounters the
second fscanf() which is the condition of the "if" statement.

If one was at a \r or \n then the fscanf() at the "if" will remove all
the \r and \n that await in sequence, either leaving one at EOF or
at a character which is not \r or \n and looping back.

Inductively, this will repeat until one or the other of the fscanf()
encounters EOF; at that point, the next fscanf() *will* return EOF
and either the 'break' will take effect or the while() condition will
become false and the loop will end.


There is the case where the input starts out positioned at \r or \n
but there are characters there. In that situation, the conversion count
will be 0 for the while()'s fscanf(), but 0 != EOF so the loop body
will be executed and the inner fscanf() will consume the \r \n sequence
leading back to the case solved above.


The next bit you need to know for this to work is that fscanf()
*defines* that when EOF is reached with no conversion having taken
place, that an "input failure" is returned. And then, as was quoted,
that "input failure" is signaled by the value EOF being returned.

For more certainty, examine the example at the end of the C89
description of fscanf(), and notice that it -specifically- has
"count" becoming EOF at the end of the input stream.
 
N

Naren

Hello All,

I am extremely sorry for the delay,
Thanks for answers.

I have thing to add if i just added

while(!feof(fp) && fscanf(fp,"%[^\r\n]",h) != EOF)

It breaks the infinte loop and it works fine. Is there anything wrong
in my usage?

Thanks and Regards,
Naren.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top