Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: while loop vs do while loop reading from the file issue Date: Tue, 13 Dec 2016 12:42:54 -0800 Organization: None to speak of Lines: 161 Message-ID: References: <52f1c174-6af1-4fda-9ff8-a5e2cf507b5f@googlegroups.com> <878trmxufh.fsf@bsb.me.uk> <87d1gyw8s6.fsf@bsb.me.uk> <87inqpucmw.fsf@bsb.me.uk> <87fultqnuz.fsf@bsb.me.uk> <87bmwgpxbs.fsf@bsb.me.uk> <87mvg0o6hk.fsf@bsb.me.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="dfa63d714b7efbf23555ba45297b3f3c"; logging-data="11795"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Yi7sdBBYVKz/FVHbp0wU1" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:rbYwF09Qep3+Or+JH2rU3ue1XOc= sha1:d5kqMT1Zvx5C7l44jyb5Jy4zgtE= Xref: csiph.com comp.lang.c:99253 BartC writes: > On 13/12/2016 19:30, Keith Thompson wrote: >> BartC writes: > >>> 17 TO:Prime Minister >>> 24 FROM:Ministry of Defence >>> 27 SUBJECT:Intelligence Report >>> 15 PRIORITY:Urgent >>> 15 DATE:13/12/2016 >>> 16 ---------------- >>> 64 No intercepts from Russian military units in Ukraine. This means >>> 35 they are maintaining radio silence. >>> 0 >>> 65 Almost certainly they are preparing to attack. Request permission >>> 30 to take defensive precautions. > >> So your eof() method returns a bogus empty line when there's nothing >> more to be read. > > What makes you come to that conclusion? Do you see a bogus empty line in > the output above? I came to that conclusion from your description upthread: But if some error occurs while reading the line, after eof returns false, then a blank line is returned (due to fgets returning NULL). The /next/ eof() will then return true, assuming the error persists. >> As opposed to the usual idiomatic C way to read text, >> which clearly distinguishes between an empty line (which is valid input) >> and either end-of-file or an error condition. > > This empty line is a red herring. The body of the loop is not interested > in errors, but in the unlikely event of there being one while doing > fgets, what should be the contents of the buffer? fgets returns a null pointer on an error or end-of-file. [...] >> I'm having trouble seeing how your eof() method is an improvement over >> controlling an input loop by checking the result returned by the input >> function. > > Did you look at that link? No, I didn't. I just checked half a dozen or so parent articles, and found this: https://www.rosettacode.org/wiki/Read_a_file_line_by_line Is that the link you're referring to? That points to over 100 sample programs, 3 of them in C. Please be specific. > Why does the poor C programmer needed to be > lumbered with all this palaver when hardly any of the other languages > bother? "All this palaver" actually works. > (BTW the Ada example also uses a loop with a pre-reading EOF check. I > guess it's OK when a well-respected other language does it. But if /I/ > suggest it, it /must/ be wrong!) You do sarcasm slightly better than jacob does, but not by much. Nobody is saying there aren't alternatives. Most of us are simply saying that *in C*, the most reliable way to read input is by checking the return value of the input function, not by calling some eof() function before attempting a read. >> And since you *still* haven't shown a example of a C program using your >> eof() method, this will probably never be resolved. > > Read further up the thread. > > Meanwhile here's some code you can try out. Change 'filename' to the > name of some input text (preferably RH's message), or arrange for the > filename to come from the command line or read from stdin if you like: > > #include > #include > #include > > #define filename "KKK1" > > int myeof (FILE * f) { > int c; > c = fgetc(f); > if (c == EOF) { > return 1; > } > ungetc(c,f); > return 0; > } > > void myfgets(char * buffer,int size, FILE* handle) { > char* p; > int n; > *buffer = 0; > if (fgets(buffer,size-2,handle) == 0) { > return; > } > n = strlen(buffer); > if (n == 0) { > return; > } > p = (buffer+n)-1; > while (p >= buffer && (*p == 13 || *p == 10)) { > *p-- = 0; > } > } > > int main (void) { > FILE* f; > char line[1000]; > f = fopen(filename, "r"); > if (f == 0) { > printf("Can't open %s\n", filename); > exit(1); > } > > puts("--------- start of file --------"); > while (!myeof(f)) { > myfgets(line, sizeof line, f); > puts(line); > } > fclose(f); > puts("--------- end of file ----------"); > } Ok. Here's my program with the same functionality. #include #include #define filename "KKK1" int main(void) { char line[1000]; FILE *f = fopen(filename, "r"); if (f == NULL) { fprintf(stderr, "Can't open %s\n", filename); exit(EXIT_FAILURE); } puts("--------- start of file --------"); while (fgets(line, sizeof line, f) != NULL) { fputs(line, stdout); } fclose(f); puts("--------- end of file ----------"); } Are you claiming your approach is simpler? -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"