[comp.lang.c] Overwriting

jfw@ksr.com (John F. Woods) (05/02/91)

thurmag@jacobs.cs.orst.edu (Gary Thurman) writes:
>i am trying to use the fwrite() function to remove information from a database.
>Can you "re-write" over the top of a sector stored in the database by fwriting
>over the top of it?

Yes.  Your program below has three basic misunderstandings of how to use
stdio.  (there's actually a number of small problems in the program, I'll
just deal with the stdio problem)

First, you opened the file with mode "rb", meaning "readonly, binary format".
If you want to change the file using the same stdio stream, you must use "r+b"
or "rb+", meaning "open for reading and writing, binary format".

Second, the position at which IO happens is usually named the "file pointer"
(not to be confused with "FILE pointer"); each IO operation advances the file
pointer by the amount of IO performed, so when your application tries to do

	fread(buffer, sizeof(buffer), 1, stream);
	...
	fwrite(buffer, sizeof(buffer), 1, stream);

you are not trying to overwrite the intended record, you are trying to
overwrite the next record.  This is the second misunderstanding.

Lastly, a read-write stdio stream cannot be used for "intermingled" reading
and writing:  in order to switch from reading to writing (or vice versa),
you must do an fseek() or rewind().  (It really isn't hard to write a stdio
package that gets this right, but AT&T didn't, and now it is cast in stone
for all time by ANSI)

As it happens, fixing your second problem (didn't back up to the beginning
of the record) fixes the third problem anyway, since (of course) you do that
with fseek().  The skeleton of what you want is, therefore,

	long cookie;

	cookie = ftell(stream);
	fread(record, sizeof(record), 1, stream);

	if /* smash it */ {
		fseek(stream, cookie, SEEK_SET);
		fwrite(record, sizeof(record), 1, stream);
	}