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: Sat, 10 Dec 2016 16:52:44 -0800 Organization: None to speak of Lines: 116 Message-ID: References: <52f1c174-6af1-4fda-9ff8-a5e2cf507b5f@googlegroups.com> <5d94897b-fedc-4a28-81d0-3579e9bf754d@googlegroups.com> <4d53f1c5-b622-4425-9dfe-694c42676cae@googlegroups.com> <5d68da29-653c-42f5-8dbe-c11d3b304322@googlegroups.com> <87pokz3k5x.fsf@bsb.me.uk> <8737hv36ta.fsf@bsb.me.uk> <87lgvn1obu.fsf@bsb.me.uk> <874m2b1h03.fsf@bsb.me.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="d0d5c56ca22fa2e528cedb366e6a556f"; logging-data="28874"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19R7wZv1YxBDj0EF9QgYtwd" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:SquI0UrQalKZqU/awYmQ9BGibfc= sha1:ZWp63fHt4IA+3ReTe0nfMDf7dOg= Xref: csiph.com comp.lang.c:98751 BartC writes: > On 10/12/2016 23:50, Ben Bacarisse wrote: >> BartC writes: >>> It's just an idiom I use a lot (in fact I could go through a pile of >>> code looking for such while loops, in a way I couldn't do if the loop >>> condition was always different). >> >> That you use it a lot is not in dispute. > > That suggests that it works! > >> My gripe is that you advocate >> it's use in situations like Alla_'s. > > The OP's example used feof() as the test. I suggested that, with that > form of loop, it would be better to use a pre-read test similar to my > example. > >> Do you at least agree that in this >> sort of situation it's better simply to write: >> >> while (scanf("%d,%d,%d", &a, &b, &c) == 3) { >> ... use a, b and c ... >> } >> >> than any solution using your extra eof() function? > > OK, I tried this code on a file containing some numeric triples then > other unrelated unformatted numbers: > > int a,b,c,n; > FILE* f; > > f=fopen("kkk1","r"); > printf("F=%p\n",f); > > while ((n=fscanf(f,"%d,%d,%d", &a, &b, &c)) == 3) { > printf("ABC= %d %d %d\n",a,b,c); > > } > fclose(f); > > printf("N=%d\n",n); > > There were no output, but N was given as 1. So I noticed then it was > expecting commas, so put those in. Now it gave some output for this > input file, stopping when it got to the 300: > > 10,20,30 > 40,50,60 > 70,80,90 > > 100,110,120 > 130, > 140,150 > 160,170,180 > 190, > 200, > 210 > 220, > 230, > 240 > 250,260,270 280,290,300 > > -1 > -2 > .... > > I know scanf has some limitations, but that fact that it made sense of > this lax layout was a little surprising. A blank line is ignored, and it > doesn't care if triples are split across lines, or all appear on one > line. But it /does/ care if the last of a triple is followed by a comma, > then it will break out of the loop. This would be surprising to someone who doesn't know how scanf() works. Using scanf() for line-oriented input is not the best choice. It generally skips leading white space -- including, among other things, blanks, tabs, and newlines. The commas in the format string are required to match literally. Using scanf("%d,%d,%d", &a, &b, &c) to read CSV input where each line contains three integer fields can work -- but it fails to detect a lot of errors. It's good enough for a quick and dirty program, but it's not robuts. And IMHO the worst problem is that the behavior is undefined if the scanned value is not within the range of int. Using fgets() to read a line at a time, then sscanf() to parse the input, is more robuts. Using fgets() and strtol() is even better; it lets you detect and handle numeric overflow. Using something that can handle overly long lines would be even better. The more you want to do, the more complicated it gets. > It seems fragile, if the input is supposed to be line-oriented, such as > a CSV file that was mentioned, and won't cope if input can be comma, tab > or space-separated. Correct. > And the thing is, I can't see what's happening. The first thing I'd try > is this: > > while (fgets(buffer,sizeof(buffer),f)) { > printf("<%.*s>\n",strlen(buffer)-1,buffer); > } And now you're testing the value returned by the input function to determine when there's no more input. Good. [...] -- 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"