[comp.lang.c] Append mode

chet@uwovax.uwo.ca (02/14/90)

I know I'll be embarrassed because of this, but would someone please
tell me why program A below, when executed twice contains twenty lines
(i.e. the 2nd ten lines are inserted before the EOF mark), but program B
positions its appends after the EOF mark (so that they don't appear when
the file is typed out)? And what I can do to fix B. This happens on
Turbo C and Small C (2.2), and I presume on every C compiler.

Please reply to creider@csd.uwo.ca

Program A:
#include <stdio.h>
char entry[35];
main()
{
	FILE *fp;
	int i;

	fp = fopen("tenlines.txt","a");
	strcpy(entry,"this is an entry line");
	for (i=0; i<10; i++) 
		fprintf(fp, "%s\n", entry);
	fclose(fp);
}

==========================================
Prog B:

#include <stdio.h>

char entry[280];
char main_entry[40];
char lexical_class[20];
char eng_gloss[40];
char gram_info[80];
char semantic_fields[40];
char subent[80];
	
main()
{
	FILE *fp;

	fp=fopen("lex3.db","a");

	printf("\n\nMain entry: ");
	add_subentry(entry, main_entry);
	printf("Lexical class: ");
	add_subentry(entry, lexical_class);
	printf("English gloss: ");
	add_subentry(entry, eng_gloss);
	printf("Grammatical information: ");
	add_subentry(entry, gram_info);
	printf("Semantic fields: ");
	add_subentry(entry, semantic_fields);

	fprintf(fp, "%s\n", entry); 
	fclose(fp);	
}

add_subentry(entry, subentry)
char *entry, *subentry;
{
	gets(subentry);
	strcat(subentry,"$");
	strcat(entry,subentry);
}


Many thanks,

Chet Creider

wallace@oldtmr.dec.com (Ray Wallace) (02/14/90)

In article <4983.25d7e9db@uwovax.uwo.ca>, chet@uwovax.uwo.ca writes...
>(i.e. the 2nd ten lines are inserted before the EOF mark), but program B
>positions its appends after the EOF mark (so that they don't appear when
>the file is typed out)? And what I can do to fix B. This happens on

It looks to me like you need to add the line
	fprintf(fp, "%s\n", entry); 
to your add_subentry() function, and remove the fprintf() from the end of your
main() function.

As it was posted program B only writes to the file once, at the end of main()
it writes out your "semantic_field".

---
Ray Wallace		
		(INTERNET,UUCP) wallace@oldtmr.enet.dec.com
		(UUCP)		...!decwrl!oldtmr.enet!wallace
		(INTERNET)	wallace%oldtmr.enet@decwrl.dec.com
---

chet@uwovax.uwo.ca (02/15/90)

In message 14089 I noted a problem with the "a" mode. This is to confirm
that the C compiler on the Unix OS I use (Sun 4.0.1_Export) behaves the
same way. A (stupid) way around the problem is to open the file with
"r+" and then read to EOF before executing the fprintf() statement:

(to be inserted into program B:)

	while (!feof(fp))
		fgets(dump, 240, fp);

If this is done, with the Sun C compiler and with Turbo C (but not with
Small C 2.2), then the EOF mark will be in the proper place.

My questions with respect the different behaviour of A and B still
remain as puzzles. Note also that the first reply to the query involved
a misinterpretation of the code and is not relevant.

Thanks again for any help. Appended below is a bit of lex3.db to show
what B does:

mtu$n.$person$watu$human$
kitu$n.$thing$vitu$entity$
ona$v.$see, look at$psv. onekana$perception$
mtoto$n.$child$watoto$human$
msichana$n.$girl$wasichana$human$
kijana$n.$youth$vijana$human$
chui$n.$leopard, cheetah$chui$animal$

Chet Creider
creider@csd.uwo.ca

dfoster@jarthur.Claremont.EDU (Derek R. Foster) (02/15/90)

In article <4983.25d7e9db@uwovax.uwo.ca> chet@uwovax.uwo.ca writes:
>I know I'll be embarrassed because of this, but would someone please
>tell me why program A below, when executed twice contains twenty lines
>(i.e. the 2nd ten lines are inserted before the EOF mark), but program B
>positions its appends after the EOF mark (so that they don't appear when
>the file is typed out)? And what I can do to fix B. This happens on
>Turbo C and Small C (2.2), and I presume on every C compiler.
>[program text follows]

note: I attempted to mail this directly, but my host computer doesn't seem
to believe uwovax.uwo.ca exists. I think it's useful enough information
to post to the net, so I have. 

I don't know if this is a solution or not: just a suggestion of something
that might be related to your problem.
I don't see any reason why your two programs would definitely act 
differently. However,
I do see a POSSIBLE reason why program B might act as described, 
along with a possible reason for A's working fine.

The EOF marker character (ctrl-z on my system) is only meaningful in 
the case of text files.

In a binary file, always adding text before an EOF character would
be clearly inappropriate, since the character might actually be data in
the file.

Therefore, the C routines, if they do detection like this at all (which
they may not - if so, see option #2 below.) must
be able to tell which kind of file this is in order to tell if they should
consider the EOF character to be the end of the file, or if they should
judge file size by the "file length" field in the disk's directory entry.
(which contains the ENTIRE length of the file, INCLUDING any EOF characters
in the file as well as anything that may follow them.)

possible solution 1:
Try opening your file explicitly in text mode ie. 
  stream = fopen(filename, "at");
if your C compiler is "smart" enough to know the difference, this may solve
your problem. My logic here is that something in other routines
in the program may have messed with the value of the
_fmode system variable, which affects the default mode (text or binary) that
the file was opened in. This would explain the results you describe. (if file
A was opened in text mode, but file B was opened in binary mode.) 
If you state the mode explicitly, then you have at least removed this as a
possible source of error.

possible solution 2: "how do I get program B to work correctly"
If that doesn't work, try using the fseek function to
"back up" the stream pointer to before the EOF character.
(assuming, of course, that there is one - using an actual character
to mark the end of a text file has sort of gone out of style nowadays. 
Many editors don't automatically put one there anymore. Watch out for this.)

/* WARNING : this code fragment assumes that the file in question
   a) has at least one byte in it.
   b) has no EOF characters occurring before the actual end-of-file
      (as reported by the disk directory entry)
   c) has an EOF character as the last byte in the file.
   if you aren't SURE of any of these assumptions, you may have to include
   additional code and/or file processing.
*/
  stream = fopen(filename, "at");
  fseek(stream,-1,SEEK_END); /* position the file pointer one before the
                                end-of-file, so that the next character
                                you write will overwrite the last character
                                in the file */

My Turbo C manual states that fseek is "available on UNIX systems" so this
should be fairly portable.

Hope this helps!

Derek Riippa Foster

zvs@bby.oz.au (Zev Sero) (02/16/90)

In a previous article chet@uwovax.uwo.ca writes:
   I know I'll be embarrassed because of this, but would someone please
   tell me why program A below, when executed twice contains twenty lines
   (i.e. the 2nd ten lines are inserted before the EOF mark), but program B
   positions its appends after the EOF mark (so that they don't appear when
   the file is typed out)? And what I can do to fix B. This happens on
   Turbo C and Small C (2.2), and I presume on every C compiler.
[followed by example program A which works, and B which doesn't, even
though the relevant code looks identical].

and in article <4992.25d9633c@uwovax.uwo.ca> he writes:

   In message 14089 I noted a problem with the "a" mode. This is to confirm
   that the C compiler on the Unix OS I use (Sun 4.0.1_Export) behaves the
   same way.

Huh?  In UNIX there is no such thing as an EOF marker, so how could
"a" append after the EOF?  I had assumed that your problem only
happened in DOS.

In any case, I compiled your program B with both gcc and cc under
SunOS Release 4.0.3_EXPORT and also under Sun UNIX 4.2 Release
3.5EXPORT  and it works fine in all four versions.
--
	                                Zev Sero  -  zvs@bby.oz.au
Megalomaniacs are simply people who know damn well they can run the universe
better then God or the present governors.	- Abner Doon (Orson S. Card)