chris@mimsy.UUCP (Chris Torek) (12/11/88)
In article <846@starfish.Convergent.COM> jerry@starfish.Convergent.COM (Gerald Hawkins) writes: >Is it ever ok to use the form: [slightly edited] > if (a = b * 2 + 39) /* intentional assignment within condition */ > ... >INSTEAD OF: > a = b * 2 + 39 /* more normal */ > if (a) > ... >I say "no!" The code is unsupportable. EVERYONE who ever reads it will >assume it is a trivial error (and perhaps try to correct it). Not necessarily everyone, but it is certainly a dubious construct. This is especially true since you can write if ((a = b * 2 + 39) != 0) ... and make it clear that you did not accidentally omit one `='. I still prefer two separate statements, with one exception: /* typical sequence from Unibus drivers */ if (unit >= NFOO) return (ENXIO); ui = fooinfo[unit]; if (ui == NULL || !ui->ui_alive) return (ENXIO); Here one would like to write: ui = fooinfo[unit]; if (unit >= NFOO || ui == NULL || !ui->ui_alive) return (ENXIO); but it is not safe to refer to (fooinfo[k] where k>=NFOO). Hence: if (unit >= NFOO || (ui = fooinfo[unit]) == NULL || !ui->ui_alive) return (ENXIO); This is rather borderline; if the contents of the `if' statement were more complex I would be more solidly for it. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
frank@rsoft.UUCP (Frank I. Reiter) (12/12/88)
> Is if(a = b + c/4) (or something like this) legal ? I do it all the time, but I do it like this : |---- | if(a = b + c/4) /* Note assignment */ | whatever(); |---- Similarly I sometime code a switch like this : |---- | switch(somevar) { | case DELETE : | deletesomething(); | /* Note fall-through */ | case NEXT : | gotonextone(); | break; | case ...... |---- -- *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* Frank I. Reiter \ / UUCP: {uunet,ubc-cs}!van-bc!rsoft!frank Langley, British Columbia / \ BBS: Mind Link @ (604)533-2312 *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
djones@megatest.UUCP (Dave Jones) (12/13/88)
There is a construct that is a little awkward using standard (Pascal-like) structured statements: You want to read a value from an external source, exit the loop if the value is a sentinal, or process the value and continue if not a sentinal. { int ch; do { ch = getchar(); if(ch != EOF) process(ch); } while (ch != EOF); } The expression !EOF gets evaluated twice. A compiler that does common subexpression-removal and global flow-analysis would fix things, but not all compilers are that smart. Besides, I'm one of those old fashioned guys who wants the compiler to do what I say. Or rather, I would like to be able to say what I really want the compiler to do. So we could do this: for(;;) { int ch = getchar(); if(ch == EOF) break; process(ch); } This is nice, in as much as it moves the declaration of ch one level deeper. But it has the somewhat unstructured "break". Still, not too bad. I prefer the following: { int ch; while( (ch = getchar()) != EOF ) process(ch); } This says it almost literally, "While I get a ch that is not a sentinal, I want to continue processing."
badri@valhalla.ee.rochester.edu (Badri Lokanathan) (12/14/88)
In article <14945@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes: > I still prefer two separate statements, with one exception: > (example follows.) I am missing something here. Why is a = expr; if (a == b) {statement} preferable, in general, to if ((a = expr) == b) {statement} I think the second form is more concise and often more readable, as per K & R II ed., pp. 16-17. -- "I care about my fellow man {) badri@ee.rochester.edu Being taken for a ride, //\\ {ames,cmcl2,columbia,cornell, I care that things start changing ///\\\ garp,harvard,ll-xn,rutgers}! But there's no one on my side."-UB40 _||_ rochester!ur-valhalla!badri
ok@quintus.uucp (Richard A. O'Keefe) (12/14/88)
In article <1071@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes: >{ int ch; > while( (ch = getchar()) != EOF ) > process(ch); >} > >This says it almost literally, "While I get a ch that is not >a sentinal, I want to continue processing." I very much like embedded assignments, but that's a poor argument. To exit a loop when you find a sentinel (that's two Es, no As), you can do /* C version */ -- ADA version for (;;) { loop ch = getchar(); get(ch); if (ch == EOF) break; exit when ch = sentinel; process(ch); process(ch); } end loop I use the "while" version as an idiom for reading from a stream, but it isn't as general a method as the use of 'break'.
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/14/88)
In article <1683@valhalla.ee.rochester.edu> badri@valhalla.ee.rochester.edu (Badri Lokanathan) writes: >I am missing something here. Why is >a = expr; if (a == b) {statement} >preferable, in general, to >if ((a = expr) == b) {statement} Writing a whole bunch of unrelated actions on the same line of text isn't particularly readable no matter what the actions are. Try a = expression; if ( a == b ) statement There are several principles of style that apply to coding. One that is relevant here is: Actions that are thought of as separate tasks should be separated visually. If setting the value of `a' is conceptually only loosely related to determining whether `a' now matches `b', then it is better to visually separate these actions. On the other hand, if they are best thought of as closely coupled, then combining them is appropriate: for ( p = &qhead; (p = p->link) != &qhead; ) /* operate on node *p */ Sometimes, as in this example, it's really a "judgement call". for ( p = qhead.link; p != &qhead; p = p->link ) /* operate on node *p */ is just about as acceptable. However, the following is poor: p = qhead.link; while ( p != &qhead ) { /* operate on node *p */ p = p->link; } C's "for" statement was designed for bringing together visually all the parts of loop control; use it for that. (A recent posting showed a "for" statement whose three parts were not all involved in controlling the loop; that violates the stylistic principle I gave above.) I agree with the recommendation that programmers read "The Elements of Programming Style" by Kernighan and Plauger. There are other books that give good stylistic advice, but that's the best starter. Incidentally, this book doesn't use C in its examples, but the principles are valid for most programming languages. There isn't any way to automate good programming style, any more than there is any good way to guarantee good program design. Careful thought is essential.
chris@mimsy.UUCP (Chris Torek) (12/14/88)
>In article <14945@mimsy.UUCP> I wrote: >>I still prefer .... In article <1683@valhalla.ee.rochester.edu> badri@valhalla.ee.rochester.edu (Badri Lokanathan) writes: >I am missing something here. Why is > >a = expr; if (a == b) {statement} > >preferable, in general, to > >if ((a = expr) == b) {statement} It is not. That is why I said `I prefer' rather than `it is better'. The one that I believe is objectively worse than its alternatives is if (l = r) ... vs any of 0. l = r; if (l) ... 1. l = r; if (l != 0) ... 2. if ((l = r) != 0) ... -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
ark@alice.UUCP (Andrew Koenig) (12/15/88)
In article <861@quintus.UUCP>, ok@quintus.uucp (Richard A. O'Keefe) writes: > I very much like embedded assignments, but that's a poor argument. > To exit a loop when you find a sentinel (that's two Es, no As), you can do > /* C version */ -- ADA version > for (;;) { loop > ch = getchar(); get(ch); > if (ch == EOF) break; exit when ch = sentinel; > process(ch); process(ch); > } end loop > > I use the "while" version as an idiom for reading from a stream, > but it isn't as general a method as the use of 'break'. Once upon a time I proposed an extension to the C syntax that would allow a loop to have its (only) exit in the middle, rather than at the beginning or end. In that syntax, the example above would have looked like this: do ch = getchar(); while (ch != EOF) process(ch); or, with braces: do { ch = getchar(); } while (ch != EOF) { process(ch); } You will see that this syntax sort of merges do S while (E); and while (E) S into do S while (E) S2 with the first two simply becoming degenerate forms of the third. I couldn't sell anyone on the idea at the time. It's way too late now, of course. -- --Andrew Koenig ark@europa.att.com
logan@vsedev.VSE.COM (James Logan III) (12/16/88)
In article <8536@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
#
# Once upon a time I proposed an extension to the C syntax
# [ explanation of construct deleted ]
#
# do {
# ch = getchar();
# } while (ch != EOF) {
# process(ch);
# }
#
It looks sort of strange, but when I read it I immediately
thought of a few recent situations where it would have been
handy.
-Jim
--
Jim Logan logan@vsedev.vse.com
(703) 892-0002 uucp: ..!uunet!vsedev!logan
inet: logan%vsedev.vse.com@uunet.uu.net
evil@arcturus.UUCP (Wade Guthrie) (12/17/88)
The sound of a programmer trying to read a C program flinging himself against a wall. In article <8536@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes: > do ch = getchar(); > while (ch != EOF) > process(ch); > or, with braces: > do { > ch = getchar(); > } while (ch != EOF) { > process(ch); > } I really do not mean to flame this person, but the above constructions are EXCEEDINGLY hard to read. I much perfer the method which already exists: while ( (c=getchar()) != EOF) process(c); because it is easier for humans to parse (not to mention the fact that it requires less space. Wade Guthrie Rockwell International Anaheim, CA (Rockwell doesn't necessarily believe / stand by what I'm saying; how could they when *I* don't even know what I'm talking about???)
peter@ficc.uu.net (Peter da Silva) (12/18/88)
In article <3049@arcturus>, evil@arcturus.UUCP (Wade Guthrie) writes: > The sound of a programmer trying to read a C program flinging himself > against a wall. Is that like the sound of one hand clapping? > In article <8536@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes: > > do ch = getchar(); > > while (ch != EOF) > > process(ch); > > or, with braces: > > do { > > ch = getchar(); > > } while (ch != EOF) { > > process(ch); > > } This is a wonderful and clean extension to 'C' that solves the loop problem once and for all! > I really do not mean to flame this person, but the above constructions > are EXCEEDINGLY hard to read. I much perfer the method which already > exists: Only if you're not used to it. have you ever done extensive bourne-shell or Forth programming, where this construct is a common idiom? > while ( (c=getchar()) != EOF) > process(c); How about (in K&R indenting style, for consistancy): do { Ask question. Get answer. Categorise answer. } while(answer != exit) { Stuff... switch(answer) { ... } And more stuff... } That is, what about the case where the first part of the loop is too complex to fit in a while statement. Sure, you could put a break in, but isn't this clearer? The existing while and do loops become special cases. -- Peter da Silva, Xenix Support, Ferranti International Controls Corporation. Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180. Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net.