Article View: comp.std.c
Article #3428Re: Multi-level break and elimination of GOTO
From: A. van Kessel
Date: Thu, 21 Sep 1995 19:01
Date: Thu, 21 Sep 1995 19:01
99 lines
3806 bytes
3806 bytes
Can we please *STOP* this religious wars ?
It is beginninning to look like YOUGOSLAVIA here ...
Ok, a last contribution to this amusing thread:
I have a lot of small text-scanning programmes, implementing
finite state automata but still to trivial to force me into
Yacc. The GOTO-less solution in my case ( ;-) ) is GOTO-less
spagetti like:
/* unchecked code: may contain language that is offending
* to compilers.
* Watch out !!! the rest of this comment is for
* First grade students trying to do their homework
*
* BEWARE! lots of (EOF,oldstate,etc0) checking omitted !
* Lots of semicolons left out.
* Exercise: get it working.
* Question: what does it do.
* Advanced: alter it to recognize NUMBERS
* (if successfull: try float numbers)
* If you were succesfull:How many states does it take?
* can you reduce it to 8 states ??
* Can you extend it to assign the numbers to an array ?
* can you dynamically reallocate the array ?
* Disclaimer: This code does NOT work without modification;
* it is supplied as an example of (pathologic) style in a
* terminal phase.
*/
enum _state { init, leadwhite, word, trailwhite, done} state;
int ch=EOF;
for (state=init; state != done; ) {
if (ch == EOF) ch = fgetc(fp);
if (ch == '\n') break;
if (ch == EOF) state = done;
switch (state) {
case init: /* sorry I dont indent on labels */
if (ch == ' ') state = leadwhite;
else state = word;
break;
case leadwhite:
if (ch != ' ') state = word;
else ch = EOF;
break;
case word:
if (ch == ' ') state = trailwhite;
else ch = EOF;
break;
case trailwhite:
if (ch != ' ') state = done;
else ch = EOF;
break;
case done:
fprintf(stderr,"This should NEVER happen, Call QC\n");
break;
} /* switch */
} /* for */
/* please note that some of the breaks above can be omitted/avoided
* Hint: if you ever USE this construct, start witch breaks
*/
After jump-optimizing this reduces to something like:
while (1) {
/* fgetc() stuff */
if (ch == ' ') if (characters_seen) goto trail; else goto lead;
else goto word;
init: if (ch ...) goto white;
else goto word
white: if (ch ...) goto word
else ...
continue;
word: if (ch ...) goto trail;
else ...
continue
trail: if (ch ...) goto done;
else ...
continue;
done: barf();
break;
} /* while */
/* This last form is what most LEXes generate, but extensively
* decorated with buffer-maintenance and wild returns.
* LEX produces human-unreadable code, that is its
* purpose. But it *does* supply state-diagrams/transition-diagrams,
* (if asked todo so) and I dont (unless forced todo so).
*/
WHICH IS BASICALLY THE SAME, BUT CONTAINS ONLY ONE LEVEL OF BRACES !!
So it is all just a matter of style, no more , no less.
The usability of either method depends on the amount of EXPLICIT state
that you want: if there is a lot of state, you'd better make it explicit
(which means OVERcoding, as an analog of over-acting), otherwise you will
not be able to understand your own code after a few days.
That's My 2 cents!
Happy hacking,
Adriaan van Kessel.
Technical Details
Message-ID:
<DF9rIF.9uE@rivm.nl>Path:
arc1-ca.pugleaf.net!news.nic.surfnet.nl!sun4nl!rivm!newsReferences:
<43pdut$hoh@galaxy.csc.calpoly.edu> <DF8FE3.97H@news.cern.ch>Show Full Headers
Complete Article Headers
Newsgroups: comp.std.c,comp.lang.c Path: arc1-ca.pugleaf.net!news.nic.surfnet.nl!sun4nl!rivm!news From: "A. van Kessel" <imaavk> Subject: Re: Multi-level break and elimination of GOTO Content-Type: text/plain; charset=us-ascii Message-ID: <DF9rIF.9uE@rivm.nl> To: loreti@axcdf1.pd.infn.it Sender: news@rivm.nl Content-Transfer-Encoding: 7bit Organization: Rijksinstituut voor Volksgezondheid en Milieuhygiene, Bilthoven, NL References: <43pdut$hoh@galaxy.csc.calpoly.edu> <DF8FE3.97H@news.cern.ch> Mime-Version: 1.0 Date: Thu, 21 Sep 1995 19:01:26 GMT X-Mailer: Mozilla 1.1N (X11; I; OSF1 V3.0 alpha) X-Url: news:DF8FE3.97H@news.cern.ch