end-of-file problem

B

boa

* Markus Pitha wrote, On 20.08.2006 15:01:
Hello,

I read a simple bmp-file with this loop:

while ( !feof(fp) ) {
printf("%x\n", fgetc(fp));
}
fclose(fp);

Everything seems to be correct,

It isn't, see the faq for details. http://c-faq.com/stdio/feof.html
but at the end of the file, I get a weird
"ffffffff" output. How does this come? Actually the loop must have been
finished before printf can print some data, or when will the file
pointer increased in this case?


ffffffff happens to be the same as -1 on most machines. EOF also happens
to be -1 on most machines. So you're printing the value of EOF, returned
from fgetc(). On the next iteration, feof() returns true and your loop
stops.

boa
 
C

CBFalconer

Markus said:
I read a simple bmp-file with this loop:

while ( !feof(fp) ) {
printf("%x\n", fgetc(fp));
}
fclose(fp);

Everything seems to be correct, but at the end of the file, I get
a weird "ffffffff" output. How does this come? Actually the loop
must have been finished before printf can print some data, or when
will the file pointer increased in this case?

Nothing weird about it. It is simple misuse of the feof function.

int ch;

while (EOF != (ch = getc(fp)) {
printf("%x\n", fgetc(fp));
}
if (!feof(fp)) puts("Hardware error occured");

feof does not look forward, as in better languages. It
distinguishes between i/o errors and reaching EOF when an input
statement fails. To distinguish between EOF and all normal chars
it is necessary to receive those chars into an int, rather than a
char.

getc is normally preferable to fgetc when the file argument can be
evaluated more than once.
 
B

boa

* Markus Pitha wrote, On 20.08.2006 16:36:
Hello,

thanks for the link but I couldn't handle it as in this example. I
got warnings of comparing pointers with NULL and therefore a bad program
behaviour like endless loops.
Now I decided to use the following construct:

fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
rewind(fp);

while (ftell(fp) < filesize) {
printf("%x\n", fgetc(fp));
}
fclose(fp);


Please don't.

How about something like this instead?
int c;

while( (c = fgetc(fp)) != EOF)
printf("%x\n"; c);


Boa

[snip]
 
M

Markus Pitha

Hello,

I read a simple bmp-file with this loop:

while ( !feof(fp) ) {
printf("%x\n", fgetc(fp));
}
fclose(fp);

Everything seems to be correct, but at the end of the file, I get a weird
"ffffffff" output. How does this come? Actually the loop must have been
finished before printf can print some data, or when will the file
pointer increased in this case?


Thanks,
Markus
 
S

spibou

Markus said:
I thought this is only allowed with text files because of the fact that
EOF is defined as -1 and binary files could contain "-1"?

No , it is allowed with all files. EOF will be defined in a
way that the value cannot appear in a file on your platform.
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Markus said:
I thought this is only allowed with text files because of the fact that
EOF is defined as -1 and binary files could contain "-1"?

fgetc() always returns either an unsigned char converted to int, or EOF. As
long as c is wide enough to hold both EOF and 0 ... UCHAR_MAX, for example
with c declared as int as it was in the message you replied to, there's no
problem. With c declared as char, there would be a problem.
 
F

Flash Gordon

CBFalconer said:
Nothing weird about it. It is simple misuse of the feof function.

int ch;

while (EOF != (ch = getc(fp)) {
printf("%x\n", fgetc(fp));

Did you really mean to read another character and print it, thereby
printing every other character? * think you meant:
printf("%x\n", ch);
}
if (!feof(fp)) puts("Hardware error occured");

feof does not look forward, as in better languages. It
distinguishes between i/o errors and reaching EOF when an input
statement fails. To distinguish between EOF and all normal chars
it is necessary to receive those chars into an int, rather than a
char.
Agreed.

getc is normally preferable to fgetc when the file argument can be
evaluated more than once.

I would say that it is extremely rare to need fgetc rather than getc. I
understand the code constructs which would require it, e.g.
fgetc(fparr[i++), I just can't think of anywhere where they would have
been useful to me. Has anyone here actually done something where they
had to use fgetc rather than getc?
 
M

Markus Pitha

Hello,

thanks for the link but I couldn't handle it as in this example. I
got warnings of comparing pointers with NULL and therefore a bad program
behaviour like endless loops.
Now I decided to use the following construct:

fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
rewind(fp);

while (ftell(fp) < filesize) {
printf("%x\n", fgetc(fp));
}
fclose(fp);
ffffffff happens to be the same as -1 on most machines.
to be -1 on most machines. So you're printing the value of EOF, returned
from fgetc(). On the next iteration, feof() returns true and your loop
stops.

Thanks, that sounds plausible to me.
 
M

Markus Pitha

boa said:
while( (c = fgetc(fp)) != EOF)
printf("%x\n"; c);

I thought this is only allowed with text files because of the fact that
EOF is defined as -1 and binary files could contain "-1"?
 
M

Markus Pitha

Harald said:
fgetc() always returns either an unsigned char converted to int, or EOF. As
long as c is wide enough to hold both EOF and 0 ... UCHAR_MAX, for example
with c declared as int as it was in the message you replied to, there's no
problem. With c declared as char, there would be a problem.

I understand, thanks to everybody.


Markus
 
B

Bill Pursell

Markus said:
Hello,

thanks for the link but I couldn't handle it as in this example. I
got warnings of comparing pointers with NULL and therefore a bad program
behaviour like endless loops.
Now I decided to use the following construct:

fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
rewind(fp);

This is slightly OT, but this particular technique is
really annoying. By doing this, you make it impossible
to run your program on anything but a regular file.
If you try to execute the code on a fifo or a stream
the seek will fail. You almost never need to know
the size of the file before you start processing. If
you do need to know it, you should find its size
using whatever mechanism is provided by your
platform (eg fstat()). Granted, if you do need to
know the file size, then it probably doesn't make
sense to run the program on a fifo or a stream,
but it's a really good idea to expect your program
to be modified at a later time to be used on an
input stream. For this example, (basically an
implementation of xxd), it is very easy to see someone
wanting to run it on a fifo and watching the output
as it progresses.
 
M

Mark McIntyre

Hello,

thanks for the link but I couldn't handle it as in this example. I
got warnings of comparing pointers with NULL and therefore a bad program
behaviour like endless loops.

Then why not ask about that problem, and maybe someone can help fix
it?

I get this all the time with users, asking the wrong question...

I can't login, can you reset my password to 'potato' please
your existing password isn't expired, did you try that?
I can't use it any more.
why not, its still valid?
I can't type it.
why not?
its got an 'e' in it
pardon, whys that a problem?
I poured coffee in my keyboard and the 'e' is broken, so I need a new
password....

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Mark McIntyre

I thought this is only allowed with text files because of the fact that
EOF is defined as -1 and binary files could contain "-1"?

NO. NO. NO. Do not confuse the EOF condition with the EOF character!

EOF is NOT a value read from the file, its a condition returned by the
library to indicate there's no more data. It works for any sort of
file (as long as itr has an end).
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
K

Keith Thompson

Mark McIntyre said:
NO. NO. NO. Do not confuse the EOF condition with the EOF character!

Better:

Do not confuse the end-of-file condition with the value of the EOF
macro.
EOF is NOT a value read from the file, its a condition returned by the
library to indicate there's no more data. It works for any sort of
file (as long as itr has an end).

End-of-file is a condition. EOF is a macro that expands to a value of
type int; this value is returned by certain library functions to
indicate that there's no more data, and it's distinct from any valid
character value (since EOF is negative, and a character read from a
file is interpreted as unsigned char and then converted to int).
getchar(), for example, returns the EOF value to indicate an
end-of-file (or error) condition.
 
M

Mark McIntyre

Better:

Do not confuse the end-of-file condition with the value of the EOF
macro.

Thats not what I meant - I was referring to the character EOF in the
ASCII set.

Mind you,. it'd be less confusing had the committee not decided to
call both the macro and the function EOF, case notwithstanding, and
share that with a quite different ASCII code.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
K

Keith Thompson

Mark McIntyre said:
Thats not what I meant - I was referring to the character EOF in the
ASCII set.

Ok, that's what confused me.

<OT>
There is no ASCII character called "EOF". The ASCII control
characters are:

NUL SOH STX ETX EOT ENQ ACK BEL
BS HT LF VT FF CR SO SI
DLE DC1 DC2 DC3 DC4 NAK SYN ETB
CAN EM SUB ESC FS GS RS US

DEL
Mind you,. it'd be less confusing had the committee not decided to
call both the macro and the function EOF, case notwithstanding, and
share that with a quite different ASCII code.

Um, the function is called feof(), not EOF.
 
J

Joe Wright

Mark said:
Thats not what I meant - I was referring to the character EOF in the
ASCII set.
[ snip }

There is no EOF character in the ASCII set. Never has been.

The EOF character was invented, as far as I know, by Gary Kildall at
Digital Research for CP/M 80. The CPM filesystem's directory entry
defined a file's length as a number of 128-byte unit records.

That was all well and good for binary and executables, but what about
ASCII text files? If you would concatenate two text files you need to
know where the first one ends, to the byte, not the unit record.

CPM implemented the EOF character (^Z or Ctrl-Z or 0x1a) to address the
problem. The EOF character was a signal to the BIOS that the previous
character was the LAST character in this text stream.
 
K

Keith Thompson

Joe Wright said:
There is no EOF character in the ASCII set. Never has been.

The EOF character was invented, as far as I know, by Gary Kildall at
Digital Research for CP/M 80. The CPM filesystem's directory entry
defined a file's length as a number of 128-byte unit records.

That was all well and good for binary and executables, but what about
ASCII text files? If you would concatenate two text files you need to
know where the first one ends, to the byte, not the unit record.

CPM implemented the EOF character (^Z or Ctrl-Z or 0x1a) to address
the problem. The EOF character was a signal to the BIOS that the
previous character was the LAST character in this text stream.

<OT>ASCII refers to that character as SUB (substitute).</OT>
 
J

Joe Wright

Keith said:
<OT>ASCII refers to that character as SUB (substitute).</OT>
You are correct. Thanks for sharing. At my house..

| 0 NUL| 1 SOH| 2 STX| 3 ETX| 4 EOT| 5 ENQ| 6 ACK| 7 BEL|
| 8 BS | 9 HT | 10 LF | 11 VT | 12 FF | 13 CR | 14 SO | 15 SI |
| 16 DLE| 17 DC1| 18 DC2| 19 DC3| 20 DC4| 21 NAK| 22 SYN| 23 ETB|
| 24 CAN| 25 EM | 26 SUB| 27 ESC| 28 FS | 29 GS | 30 RS | 31 US |

...but even knowing the names of the things, I don't remember what SUB
and several others are supposed to do. Do you?
 

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
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top