bill@twwells.uucp (T. William Wells) (12/23/88)
In article <8@estinc.UUCP> fnf@estinc.UUCP (Fred Fish) writes: : Since this is my pet peeve #1 about C style, I couldn't resist. There : is no ambiguity if you simply make it a habit to ALWAYS include braces : for {if, while, do, for} etc, even when they are not strictly necessary. Absolutely. One should always include optional braces. There are two advantages: 1) A decrease in the likelyhood of programming errors. 2) An increase in the readability of the program. One should also never write a compound statement on the same line as the head of the statement it is embedded in. E.g., instead of: for (a; b; c) statement; one should write: for (a; b; c) { statement; } Doing that makes finding the statement quite a bit easier. : I was recently helping out a freshman CS major with her C homework and : found out, to my horror, that the teacher in the course was marking : off points for code which included braces when they weren't strictly : required. They were teaching her to write code like: : : inchar = getchar (); : while (inchar != EOF) : if (inchar == 0) : goto done; : else : inchar = getchar (); : done: return inchar; : : Ickkk!!! Double Ickkkk!!!! A goto where a break would have done. --- Bill {uunet|novavax}!proxftl!twwells!bill
cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) (12/24/88)
In article <271@twwells.uucp>, bill@twwells.uucp (T. William Wells) writes: > In article <8@estinc.UUCP> fnf@estinc.UUCP (Fred Fish) writes: > ... > : I was recently helping out a freshman CS major with her C homework and > : found out, to my horror, that the teacher in the course was marking > : off points for code which included braces when they weren't strictly > : required. They were teaching her to write code like: > : > : inchar = getchar (); > : while (inchar != EOF) > : if (inchar == 0) > : goto done; > : else > : inchar = getchar (); > : done: return inchar; > : > : Ickkk!!! > > Double Ickkkk!!!! A goto where a break would have done. This is yet another tripple icky example of CS professors thinking that just because they can get the example programs in K&R to compile, and because they did work in Fortran in their thesis on astrophysics, they are qualified to teach C (or any other language). Wrong, wrong, wrong. Any C guru qualified (in my humble opinion) to teach C would be trying to teach code which looks like: /* * assume students have not learned the ',' operator yet */ do { inchar = getchar(); } while(inchar != EOF && inchar); return inchar; Personally, I haven't decided whether the while should be lined with the do or the loop body yet, but I like the brace alignment this way. -- Christopher J. Calabrese AT&T Bell Laboratories att!ulysses!cjc cjc@ulysses.att.com
peter@ficc.uu.net (Peter da Silva) (12/25/88)
In article <11037@ulysses.homer.nj.att.com>, cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes: > /* > * assume students have not learned the ',' operator yet > */ > do { > inchar = getchar(); > } while(inchar != EOF && inchar); > return inchar; I would recommend in this instance to make the test experession: inchar != EOF && inchar != '\0' Since inchar is obviously not a boolean (it has three distinct possible values: EOF, 0, and anything else). -- 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. 'U` Opinions may not represent the policies of FICC or the Xenix Support group.
mat@mole-end.UUCP (Mark A Terribile) (12/27/88)
: : ... helping out a freshman CS major with her C homework [I] found out ... : : that the teacher ... was marking off points for code which [used] braces : : when they weren't strictly required. They were teaching her to write ...: : : : : inchar = getchar (); : : while (inchar != EOF) : : if (inchar == 0) : : goto done; : : else : : inchar = getchar (); : : done: return inchar; : : : : Ickkk!!! : Double Ickkkk!!!! A goto where a break would have done. Let's see how many violations of good form we can see. There's the use of a goto, period. There's the use of a goto where a break would serve. There's the use of an else after a goto or break. (Some would praise this. I don't. See the example on p. 45 of Kernighan and Plaugher, *The Elements of Programming Style*, featuring the label ``NEXT_C'' . It's a splendid example of dead-spot-in-code-before-else.) There's the use of a goto to break multiple levels of structure without closing braces to remind the reader how many levels are being broken. There are two seperate calls to getchar() at opposite ends of the loop, one for the first pass, and one for all subsequent passes. There are two adjacent levels of control structure, both omitting braces. This is not only a readability disaster, but a maintainance nightmare. There's the use of a goto and label to fold surruptitiously two exits from the loop into one. It's really tough to see at a glance both the goto-exit and the loop's natural exit-from-the-top. There's the use of a `` goto X; ... X: return y; '' If the purpose of the loop is to return a value at a certain point, then the return ought to be right in the loop, with the bottom exit return a special case. There's the treatment of two effectively symmetrical cases in vastly different ways--return on EOF by the loop's control clause, and return on value zero by a goto, and what is worse, a goto that purports (by it's placement in the if-else) to be coordinate (rather than subordinate or superior) to the loop-continuation operation. Whew! That's enough for the moment. I'd deem it a favor to future generations of programmers and to the industry as a whole if someone would collect the responses from the net and mail them to the wall-eyed buzzard, and to that buzzard's superiors. And I'll bet a very nice dinner that I've written more code for which customers ultimately paid real dollars than he has. -- (This man's opinions are his own.) From mole-end Mark Terribile
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/27/88)
In article <11037@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes: >In article <271@twwells.uucp>, bill@twwells.uucp (T. William Wells) writes: >> In article <8@estinc.UUCP> fnf@estinc.UUCP (Fred Fish) writes: >> : ... They were teaching her to write code like: >> : inchar = getchar (); >> : while (inchar != EOF) >> : if (inchar == 0) >> : goto done; >> : else >> : inchar = getchar (); >> : done: return inchar; >Any C guru qualified (in my humble opinion) to teach >C would be trying to teach code which looks like: > do { > inchar = getchar(); > } while(inchar != EOF && inchar); > return inchar; Here's mine. The exact formatting is NOT IMPORTANT. What DOES matter is the comments and the fact that it is obvious how one gets each possible return value. #include <stdio.h> #define MAGIC '\0' /* silly terminating character value */ int /* returns EOF or MAGIC (why??) */ some_function( void ) /* ANSI C assumed; else delete "void" */ { int c; /* character from standard input */ while ( (c = getchar()) != EOF ) if ( c == MAGIC ) return MAGIC; return EOF; }
pcg@aber-cs.UUCP (Piercarlo Grandi) (01/03/89)
In article <11037@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes: # In article <271@twwells.uucp>, bill@twwells.uucp (T. William Wells) writes: # > In article <8@estinc.UUCP> fnf@estinc.UUCP (Fred Fish) writes: # > ... # > : I was recently helping out a freshman CS major with her C homework and # > : found out, to my horror, that the teacher in the course was marking # > : off points for code which included braces when they weren't strictly # > : required. They were teaching her to write code like: # > : # > : inchar = getchar (); # > : while (inchar != EOF) # > : if (inchar == 0) # > : goto done; # > : else # > : inchar = getchar (); # > : done: return inchar; # > : # > : Ickkk!!! # > # > Double Ickkkk!!!! A goto where a break would have done. # This is yet another tripple icky example of CS professors # thinking that just because they can get the example programs # in K&R to compile, and because they did work in Fortran in # their thesis on astrophysics, they are qualified to teach # C (or any other language). Wrong, wrong, wrong. # # Any C guru qualified (in my humble opinion) to teach # C would be trying to teach code which looks like: # # /* # * assume students have not learned the ',' operator yet # */ # do { # inchar = getchar(); # } while(inchar != EOF && inchar); # return inchar; # # Personally, I haven't decided whether the while should be lined # with the do or the loop body yet, but I like the brace alignment # this way. I would beg to suggest the following for the loop: for ( inchar = fgetc(stdin); inchar != EOF && inchar != '\0'; inchar = getc(stdin) ); Just to make it evident that this is a sequential scan. I use fgetc(3) to initialize inchar because it does not get expanded inline (unless of course I knew that in most cases the loop would be exited immediately).. The following solution is more compact and arguably more in the C tradition, but I think that making explicit the iteration structure with a for(;;) and the explicit test against '\0' are somewhat more readable. while ((inchar = getchar()) && inchar != EOF); -- Piercarlo "Peter" Grandi INET: pcg@cs.aber.ac.uk Sw.Eng. Group, Dept. of Computer Science UUCP: ...!mcvax!ukc!aber-cs!pcg UCW, Penglais, Aberystwyth, WALES SY23 3BZ (UK)
fransvo@htsa.uucp (Frans van Otten) (01/03/89)
In article <9235@smoke.BRL.MIL> gwyn@brl.arpa writes: > #include <stdio.h> > #define MAGIC '\0' /* silly terminating character value */ > int /* returns EOF or MAGIC (why??) */ > some_function( void ) /* ANSI C assumed; else delete "void" */ > { > int c; /* character from standard input */ > while ( (c = getchar()) != EOF ) > if ( c == MAGIC ) > return MAGIC; > return EOF; > } How do you like it my way: #include <stdio.h> int f() { int ch; while ((ch = getchar()) != EOF && c) /* find EOF or '\0' */ return (ch); } Any C programmer will understand how this function works; it takes less space, because it is shorter, etc. So: Why is my solution too simple ? -- Frans van Otten Algemene Hogeschool Amsterdam Technische en Maritieme Faculteit fransvo@htsa.uucp
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/04/89)
In article <683@htsa.uucp> fransvo@htsa.UUCP (Frans van Otten) writes: >In article <9235@smoke.BRL.MIL> gwyn@brl.arpa writes: >> #define MAGIC '\0' /* silly terminating character value */ >How do you like it my way: > while ((ch = getchar()) != EOF && c) /* find EOF or '\0' */ >Any C programmer will understand how this function works; it takes less >space, because it is shorter, etc. So: Why is my solution too simple ? There is more to programming than simply writing code to short-range specs. My approach has the following practical advantages: 1) The role of the "magic" terminating character is clear. 2) It is easier to comprehend, because the different return conditions are clearly spelled out. 3) Questionable points of the design were flagged. In a real project, these would be investigated and probably revised. 4) If the magic character ever needs to be changed, it is easy to do in my version, and virtually impossible to go wrong. If this sounds like an ad for Kernighan & Plauger's "The Elements of Programming Style", well...
decot@hpisod2.HP.COM (Dave Decot) (01/05/89)
> In article <9235@smoke.BRL.MIL> gwyn@brl.arpa writes: > > #include <stdio.h> > > #define MAGIC '\0' /* silly terminating character value */ > > int /* returns EOF or MAGIC (why??) */ > > some_function( void ) /* ANSI C assumed; else delete "void" */ > > { > > int c; /* character from standard input */ > > while ( (c = getchar()) != EOF ) > > if ( c == MAGIC ) > > return MAGIC; > > return EOF; > > } > > #include <stdio.h> > > int f() > { int ch; > while ((ch = getchar()) != EOF && c) /* find EOF or '\0' */ > return (ch); > } > > Any C programmer will understand how this function works; it takes less > space, because it is shorter, etc. So: Why is my solution too simple ? Aside from the fact that it contains a missing semicolon that will cause the fragment to fail and will not be caught by the compiler, and a use of two undefined identifiers (c and EOF) that will cause it to generate an error message, what you meant: #include <stdio.h> int f() { int ch; while ((ch = getchar()) != EOF && ch) /* find EOF or '\0' */ ; return (ch); } works fine. However, I would prefer to express the intent and usage more clearly, as: #include <stdio.h> /* f() discards standard input characters until EOF or null byte is read. Returns EOF for EOF; '\0' for null byte. */ int f() { register int c; /* input character */ while ((c = getchar()) != EOF && c != '\0') ; return c; } Dave Decot decot%hpda@hplabs.hp.com
fransvo@htsa.uucp (Frans van Otten) (01/05/89)
David T. Sandberg ({amdahl,hpda}!bungia!nis!mictl!dts) mailed me about my posting (edited): << #include <stdio.h> << << int f() << { int ch; << while ((ch = getchar()) != EOF && c) /* find EOF or '\0' */ << return (ch); << } < <Methinks thou needeth another semicolon, or thy while loop doth return <after thy first iteration... also, what the undefined 'c' variable is <intended to contain I won't guess, but in any event it seems useless <to use a variable to store a constant expression. Lastly, the <conditional expression is parsed as ((ch = getchar()) != (EOF && c)), <which finally compares the gotten character to the result of the <Boolean expression (EOF && c)... either a 0 or a 1, depending on whether <c is zero or nonzero. I agree on the semicolon; the c should, of course, have been ch (How did you guess that it was a variable ? :-) ). So far for the typos. What you write about the expression parsing is not true: In my C book it sais that the != operator has a higher priority than the && operator, so the expression will be parsed like: ( ( ( (ch = getchar() ) != EOF ) && ( ch ) ) Which makes it clear (to me) that the while loop terminates either at EOF or when ch == '\0'. <I understand the basis of what you are espousing, and agree that putting <the whole test into the conditional expression is the way to go. Here is <what I would do... you'll note that it is closer to your idea than Doug's, <but should work: < <#include <stdio.h> < <int func() <} < int ch; < do { < ch = getchar(); < } while ((ch != EOF) && (ch != '\0')); < return(ch); <} It won't work. Try an opening { to start the function block. By the way, I never use a do {} while (); because I personally don't like such a structure. But then again, I have more stupid and unbased ideas. <I'd post this as an article, but I don't have the capability to post <news from this site. ;'( Feel free to quote from it and tear me limb <from limb... I've got nothing better to do than read about it... ;') -- Frans van Otten Algemene Hogeschool Amsterdam Technische en Maritieme Faculteit fransvo@htsa.uucp
gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/06/89)
In article <9272@smoke.BRL.MIL>, I wrote: >My approach has the following practical advantages: ... I inadvertently left out an important one: 5) It is easy to change to return function values different from EOF or the terminating magic character, for example true/false.