Simple fwrite after getc macro question..

A

Andrew Kibler

Two sections of code, in the first one fwrite works, in the second one
it doesn't (ms VC++) both are identical except in the working one fseek
is used twice to set the file pointer, once just before the fwrite.
WHY???

Works:
fseek(fp, itemloc, SEEK_SET);
tmp = ReadLongBE(fp);
if (*itemsize == tmp){
printf("\n%X\n",ftell(fp));
fseek(fp, itemloc + 4, SEEK_SET); //added to make fwrite
work.
r += fwrite(itemdata, 1, *itemsize, fp);
printf("\n%X\n",ftell(fp));


Just goes through the motions, but doesn't write (even returns proper
values!!)
fseek(fp, itemloc, SEEK_SET);
tmp = ReadLongBE(fp);
if (*itemsize == tmp){
printf("\n%X\n",ftell(fp));
//no fseek, but ftell is correct.
r += fwrite(itemdata, 1, *itemsize, fp); //but this doesn't actually
write!!
printf("\n%X\n",ftell(fp)); //but the file pointer is advanced
properly


BOTH return the same values for ftell before and after the write.
The second one doesn't wrrite, but acts like it does during the debug.

The ReadLongBE (big endian) macro:

#define ReadLongBE(Stream) ((getc(Stream)<<24) + (getc(Stream)<<16) +
(getc(Stream)<<8) + (getc(Stream)))
Thanks!
 
P

Paul Jarc

Andrew Kibler said:
fseek(fp, itemloc, SEEK_SET);
tmp = ReadLongBE(fp);
if (*itemsize == tmp){
printf("\n%X\n",ftell(fp));
fseek(fp, itemloc + 4, SEEK_SET); //added to make fwrite work.
r += fwrite(itemdata, 1, *itemsize, fp);

When reading and then writing on the same stream, the C standard
requires an fseek/fsetpos/rewind in between, unless the read reached
EOF. Writing and then reading requires fflush/fseek/fsetpos/rewind in
between. (See C99+TC2 (WG14/N1124) 7.19.5.3p6.) Any given
implementation may or may not work without the fseek; yours apparently
doesn't. The usual idiom, which you might like to wrap up in a macro
or function, is fseek(fp, ftell(fp), SEEK_SET). Or, if you want to
check for errors and be able to handle file positions that don't fit
in long:
int reset_fp(FILE* fp) {
fpos_t pos;
if (fgetpos(fp, &pos)!=0) return -1;
if (fsetpos(fs, &pos)!=0) return -1;
return 0;
}


paul
 
R

red floyd

Andrew said:
[fwrite after fread question redacted]
Thanks!

I don't have a copy of the C standard (only the C++ standard) available,
but I believe that's defined as required. That is, after you fread, you
*must* fseek before you fwrite.

Unfortunately, that's one of the "included by reference to C standard"
areas. Anyone got the C standard?
 
T

TIT

Andrew Kibler sade:
Two sections of code, in the first one fwrite works, in the second one
it doesn't (ms VC++) both are identical except in the working one fseek
is used twice to set the file pointer, once just before the fwrite.
WHY???

Let me quote the C99 Standard 7.19.5.3/6:

"When a file is opened with update mode [...], both input and
output may be performed on the associated stream. However,
output shall not be directly followed by input without an
intervening call to the fflush function or to a file positioning
function (fseek, fsetpos, or rewind), and input shall not be directly
followed by output without an intervening call to a file positioning
function, unless the input operation encounters end-of-file.[...]"

TIT
 
A

Andrew Kibler

When reading and then writing on the same stream, the C standard
requires an fseek/fsetpos/rewind in between, unless the read reached
EOF.

Thanks for your fast reply. I was using
http://www.cplusplus.com/ref/cstdio/fwrite.html
as my resource, and they don't have that requirement documented :(
Strange that you have to do that.. after all, that's the point of the
file pointer, no? Having to flush the write buffer before a read makes
sense, though. Strange that fwrite would return the correct value,
too. Oh well.
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top