Breaking out of loops, in C?

Started by
42 comments, last by pex22 19 years, 4 months ago
Do something like this and ask your prof if he prefers it:
for(int count=0; count<100 && rand()%100 != 1; cout << count << endl, ++count)    ;


[grin]

(does the same as my previous code)
the rug - funpowered.com
Advertisement
The professor's constraint may have a broader message than you realize. In programming, there are often times numerous ways to solve a problem. Your professor may be trying to illustrate this by setting up these types of restrictions. A couple different solutions have been presented here, and there undoubtedly dozens more.

I'm not sure about your school's computer science program, but the program I went through taught more about the methodology of programming, rather than the nuts and bolts of a single language. Just because C/C++ has a break statement, can you guarantee that every programming language you will work with will have similar functionality? Most do, but I cannot say with absolute certainty than all do. At some point, you may need to work with a language that doesn't have a specific functionality you are used to using.

Also, there will be times (in both professional and personal situations) when you will be required to work within arbitrary constraints. This is one of them.
It doesn't seem that the OP was told "don't use break", so taking off so many points for something he didn't know about that isn't even wrong doesn't seem fair.
AP - plenty of pure and semi-pure functional languages don't have or need break statements. Recursion is the proper way of implementing 'loops' that require break in C.

However, since to be efficient you need a compiler capable of generating proper tail call optimized code, using break in C/C++ like languages is still necessary. I think it's a bit stupid to ban usage of something that is required to make code efficient and readable in C/C++/Java/C#.
It is considered proper practice (by somebody) to include all conditionals in the loop's condition and use if around blocks that should not be executed in the loop, like
while(more lines to proccess && (result == 0)){   result = do_op_1();   if(result == 0)   {      result = do_op_2();   }   if(result == 0)   {      result = do_op_3();   }   if(result == 0)   {      result = do_op_4();   }}
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk

First off, the OP did know about the 'no-break' restriction. If you're going to be breaking rules, you should be penalized. How much you are penalized is up to the professor's discretion. The penalty may have been a bit harsh, but the OP is not likely to do it again.

Apparently, the message I was trying to get across in my previous post (the previous Anonymous Poster) was misinterpreted. My point has nothing to do with the break functionality, or whether its right, or efficiency for the compiler, or whatever. My point was that not every language or situation is going to be the same. You need to be flexible enough to work within whatever guidelines you're given. The professor is not really teaching a specific language, but trying to get you to learn how to solve a particular problem. This is a much more valuable lesson.
No, it got across and you're probably right that that is *why* the lecturer was doing it. And yes, if you are breaking rules you will be penalized and that is right (I remember being penalized by making trivial optimizations to M68k assembly code when the lecturer wanted the simple versions..).

However that doesn't mean it is a sane way of doing things. 'break' is a natural Cism, if you want to show how other languages do things then show other languages - don't brain damage and already brain damaged language.

Then again, there are probably far too many constraints on the lecturer to enable him/her to teach a second language in parallel.
Many times, if I find myself putting a break in a loop that's a signal to me that the loop should probably be in a separate function, and the break should really be a return.

Things like "break when you find the item you want in a list" are almost always more cleanly implemented as a little function called FindItem(..), etc.

And... in the end... it all boils down to a jmp anyway. It's not "dangerous" by any means. I think his real goal is to have you produce the most understandable and "clear" code. IMHO, sometimes a break fits that definition (but not often.)

Suppose you have a function that searches an array for a particular item:
int search_array (int *array, int num_elements, int key);

The function returns -1 if the item isn't found and the index of the item if it is.
Using the break statement, it could look like:
int search_array (int *array, int num_elements, int key){  int    index;  for (index = 0 ; index < num_elements ; ++index)  {    if (array [index] == key)      break;  }   return index < num_elements ? index : -1;}

Not using the break, there are two possible solutions, first, using a test variable:
int search_array (int *array, int num_elements, int key){  int    found = 0,    index;  for (index = 0 ; !found && index < num_elements ; ++index)  {    if (array [index] == key)      found = 1;  }   // the above loop does an extra '++index' when the item has been found!  return found ? index - 1 : -1;}

or putting the condition in the 'for':
int search_array (int *array, int num_elements, int key){  int    index;  for (index = 0 ; array [index] != key && index < num_elements ; ++index)  {  }   return index < num_elements ? index : -1;}

which is like the 'break' version but the 'for' statement is getting a bit big and unwieldly.
To any competant C coder, the 'break' version is easily the cleanest and most understandable of the three. The second is awful because of the 'index - 1' obfuscation. The third version, whilst being OK in this example, would be hard to understand if the condition was more complex.
Finally, the first and second method allows you to put a simple execution breakpoint when the match is found whereas in the third version it's not possible to break when the match is found (unless the debugger supports conditional breakpoints but these tend to slow the system down a lot).

I think you're teacher is misguided.

Skizz

P.S. Show him Duff's Device and I'm sure his brains will turn to jelly.
Quote:Original post by DrNecessiter
Many times, if I find myself putting a break in a loop that's a signal to me that the loop should probably be in a separate function, and the break should really be a return.[...]
Returns not at the end of a function are considered 'incorrect' more often than break itself is, so actually your solution isn't really one =-)

Oh, and for those that may have misunderstood me: Yes, break (and mid-function returns) are _REALLY_ great things. Without them, code becomes much more complex. For example, today at work I had to break a ~100 line function into 3 ~80 line functions because of all the indenting(80-char line length limit) caused by eliminating 'break', 'continue', and mid-function returns. Unfortunately, one person hears it and then ends up setting policy without knowing better.

In simple cases, eliminating them is probably better, but when you're writing real code it gets messy REAL fast.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk

This topic is closed to new replies.

Advertisement