Re: File Merge



Michael R. Copeland wrote:
while ((!feof(wf3)) || (!feof(wf1)))

This is the wrong way to check for end-of-file. Please see Question 12.2 in the comp.lang.c Frequently Asked Questions (FAQ) list at

Indeed, but that's why I wanted suggestions how I can improve this kludgey logic. Regardless of the normal method to read a file, I couldn't work out a clean and simple way to loop through both files while performing the merge. I guess I'd need to see how the conventional logic applies to my particular problem (and I couldn't find anything on google on this...).

Hmmm. The FAQ seems pretty clear -- but then again, I have the advantage of already knowing the answer. "It's elementary," as Sherlock always says *after* explaining how he figured it out.

    Okay: End-of-input is only detected by attempting a read
and having it fail.  There's no way to ask "Is there any input
left?" without actually attempting an input operation.  This
may seem a silly restriction in connection with disk files,
but consider the situation when input is coming from a keyboard
or a network socket or something of the kind: There is no way
to predict that the user is about to strike ^D or ^Z or whatever
the local end-of-input key sequence is, nor is there any way to
predict that the other end of your socket connection is about
to hang up the phone on you.  You cannot know what happened
until it actually happens -- so the only way to know that you
have reached end-of-input is to try to read something and get
a failure.

    Now, end-of-file is only one of the reasons an input attempt
might fail: for example, input from a disk could fail in the
event of a head crash, or input from a keyboard could fail if
you spilled Coke Classic into the mechanism and shorted it out
with caramelized sugar.  Most of C's input functions report a
kind of "generalized failure" no matter what the cause -- and
the *only* reason feof() exists is to let you figure out that
cause.  If the function could read no more input because it
detected end-of-file, feof() will be true; if feof() is false,
the failure was something like a bad disk sector (and ferror()
will be true).

    Putting this all together, you should write code that looks
something like

	if (fgets(fgets(WDBRec, sizeof(WDBRec), wf1) == NULL) {
	    /* Woops!  Couldn't get any more input.  Why not? */
	    if (feof(wf1)){
	        /* Aha!  We've reached end-of-file, and should
	         * remember the fact and not try to read any more.
	         */
	    }
	    else {
	        /* Oh, woe!  Oh, woe!  The Nazgul have eaten
	         * the disk controller, and are even now taking
	         * the Token Ring back to Sauron!  If I were to
	         * test ferror(wf1) at this point it would return
	         * true, confirming my worst fears.
	         */
	    }
	}
	else {
	    /* Whoopee!  I got some input data! */
	}

    I hope you understand by now that it is pointless to call
feof() or ferror() *before* an input operation; they only make
sense after an input operation has already failed.

>>    You haven't shown us what copy() is.  I'm going to assume
>> that it copies the second through sixth characters (that is,
>> array elements [1] through [5]) into a six-char array somewhere
>> and appends a '\0'.  Whether this works depends a lot on the
>> location and nature of that intermediate six-char array; see
>> Question 7.5 for a description of one all-too-frequent error.
>
>    No, it is a "substr" function that copies character 1-5 of
> the input.    I didn't include some stuff I felt was extraneous
> to the logic, sorry...

    Um, er, that's exactly how I described it, is it not?  And
all the things I said about it (including the Q7.5 reference and
the stuff about repeating the final record indefinitely after
EOF) still hold.

--
Eric Sosman
esosman@xxxxxxxxxxxxxxxxxxx
.