Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84 exptools; site whuxl.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxt!houxm!whuxl!mike From: mike@whuxl.UUCP (BALDWIN) Newsgroups: net.lang.c Subject: break, continue, return, goto Message-ID: <771@whuxl.UUCP> Date: Fri, 1-Nov-85 22:22:26 EST Article-I.D.: whuxl.771 Posted: Fri Nov 1 22:22:26 1985 Date-Received: Sun, 3-Nov-85 05:33:58 EST Distribution: net Organization: AT&T Bell Laboratories, Whippany Lines: 99 This is in response to those who think that break, continue, and multiple returns are bad things. As with anything, they can be abused, but I find continue and multiple returns extremely useful for dealing with errors, and break for ending complicated search loops. In fact, that covers 99% of the ways I use them. Here are some typical examples: /* using continue for error handling in loops */ for (i = 1; i < argc; i++) { if ((fp = fopen(argv[i], "r")) == NULL) { perror(argv[i]); continue; } if (some other reason this arg is bad) { process(error); continue; } /* code to deal with a good arg */ while ((c = getc(fp)) != EOF) munch(c); } /* using break for ending a complicated search loop */ for (m = meeble; m < meeble + NMEEBLE; m++) if (m->glop == forp && m->zip == fweep) { printf("zeegle %2s", m->yorg); m->blazzo += IGUAP; break; } /* * Using multiple returns for error cases. */ int monge(file, index) char *name; int index; { if (index < 0 || index >= MAXIDX) { puts("yikes!"); return ERR; } if (stat(file, &st) < 0) { perror(file); return ERR; } if (some other reason I can't deal with this) { process(error); return error code; } /* code to deal with a good call */ chmod(file, tab[index].mode); unlink(file); calculate(newindex); return newindex; } ---- These are clear and obvious uses for break et al., and they reflect how I *think* about the problems!! E.g., in the first for loop, I think: "Ok, I have a file to process. Obviously, if I can't open it, or something weird is wrong with it, then skip it. Once all the trivial tests for validity are out of the way, go ahead and process it." Now with the next for loop, the test could be built into the for stmt, but that would be quite unreadable. I read it thusly: "Go through the meeble array. When you find a glop and zip match, do something magic, then get out." Now how would you code these things *sanely* without using break, continue, and multiple returns? Is the code you end up with the way you actually *think* about the problem? (Don't tell me you think in boolean flags!) A high level picture of how I view a block of code: block_of_code(x) /* x is an arg or a loop var */ { /* error checks */ check_validity(x); check_for_space(); check_anything_else(); /* main body of code */ process(x); munch(x); murgolate(x); } Where the checks end with continue or return. Also note that my style stops things from marching off the right side of the page because of trivial error tests. The main code that works on x is only one indentation level in. Anyway, the gist of this is: I find break, continue, and return very useful and map well into how I think (which, I'll admit, can border on paranoid schizophrenia sometimes :-) :-| :-( :-@ ), and I would be utterly lost in time, and lost in space, without them ("help me, Mommy!"). "Madness takes its toll." Michael Baldwin "Bruce" {at&t}!whuxl!mike