228

I've been programming in Java for several years now, but I just recently returned to school to get a formal degree. I was quite surprised to learn that, on my last assignment, I lost points for using a loop like the one below.

do{
     //get some input.
     //if the input meets my conditions, break;
     //Otherwise ask again.
} while(true)

Now for my test I'm just scanning for some console input, but I was told that this kind of loop is discouraged because using break is akin to goto, we just don't do it.

I understand fully the pitfalls of goto and its Java cousin break:label, and I have the good sense not to use them. I also realize that a more complete program would provide some other means of escape, say for instance to just end the program, but that wasn't a reason my professor cited, so...

What's wrong with do-while(true)?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JHarnach
  • 3,944
  • 7
  • 43
  • 48
  • 8
    I dunno if the homework tag applies, I meant it more as a question of general programming, but I'll take it. – JHarnach Jul 27 '11 at 19:55
  • 26
    Ask your teacher, that kind of stuff is pretty subjective. – Chris Eberle Jul 27 '11 at 19:55
  • 21
    I have found this article helpful to understand [what's harmful about goto](http://drdobbs.com/article/print?articleId=228700940&siteSectionName=cpp). The comparison with `break` is probably well meaning, but actually misunderstood. Perhaps you can educate your professor on this ;) In my experience professors don't know much about the craft of programming. – Magnus Hoff Jul 27 '11 at 20:04
  • 107
    The only really, undisputable bad thing about this is in my mind, the fact that `do {} while (true)` is equivalent to `while(true) {}` and the latter is by far the more conventional form and much clearer. – Voo Jul 27 '11 at 21:06
  • 13
    If anyone doesn't appreciate the simple expressive power of `break`, they should try programming in a language without it. It doesn't take too many loops before you'll wish for it! – Steven Jul 27 '11 at 21:15
  • 17
    I disagree with the homework tag. – aaaa bbbb Jul 27 '11 at 21:46
  • `do {} while (true);` nicely matches `do {} while (false);`. :^) – Tom Hawtin - tackline Jul 27 '11 at 23:36
  • 7
    Breaks are not bad, and are often good. Labeled breaks are not bad when used carefully, judiciously, and obviously. Neither one is equivalent to goto, which is a *completely arbitrary jump from anywhere to anywhere*. – jprete Jul 28 '11 at 01:03
  • @jprete, to add to your comment: labeled breaks are *wonderful* for escaping nested loops. Nested loops should be avoided, and therefor, so should labeled breaks. However, if you need 'em, use 'em. – zzzzBov Jul 28 '11 at 01:47
  • 4
    If the break escape were evil, it wouldn't have been implemented in modern languages that instead avoid goto. This said, ["real programmers aren't afraid to use GOTOs"](http://www.pbm.com/~lindahl/real.programmers.html) either :) – Halberdier Jul 28 '11 at 11:41
  • well "break" only substitutes some ifs and the use of a flag... – kokbira Jul 28 '11 at 18:12
  • 1
    And (in Delphi) you need Break to prematurely end a for-loop (as in Delphi you cannot change the value of the iterator index within the for loop body). Very useful. Wouldn't want to have to resort to while loops to iterate over an array or collection and "break" out as soon as you have found what you were looking for... – Marjan Venema Aug 02 '11 at 18:51
  • @Marjan Venema -- good point. But sure enough this need experience. Programmers not familiar with this bad of tricks will better understand the while solution (that is, the one replacing the For, not the while true do..."break"). – TheBlastOne Aug 10 '11 at 22:59
  • @TheBlastOne: Breaking out of for loops (and while loops for that matter) is part of the "standard Delpni vocabulary". If you look at more than trivial Delphi example code, you will encounter this construct pretty soon/often. – Marjan Venema Aug 11 '11 at 06:22
  • @Marjan Venema: Yeah, I did not disagree on that. – TheBlastOne Aug 11 '11 at 06:31
  • I was called up in front of the class because I did this on a test. The reason I was called out was because I did `do while(true)`, not because I used `while(true)`. My professor said `do while true` was confusing to read, and since a `do while true` is functionally the same as a `while true` there's no reason not to use the latter, which is easier to read straight off. I disagree with the people down there who say that using a `while true break` is the same as using a boolean in the `while`. A break statement is fundamentally different, since it terminates at that spot. – jfa Feb 13 '14 at 00:21
  • 1
    The academic reaction to the spaghetti code in languages without more powerful flow controls mechanisms than `GOTO` has been very strong and if you unconditionally accept the "GOTO is bad" statement it is very easy to extrapolate into that "any GOTO-like flow mechanism is bad". Sounds like it happened here. I've found that I rarely have the need for `break`/`continue` but frequently for refactoring out a method where they are then replaced by `return`. – Thorbjørn Ravn Andersen Jul 29 '15 at 14:56
  • re: What's wrong with `do-while (true)`? Apart from `while-do` being clearer, I think main reason some senior programers tell students don't use `while-loops` use `for-loops` instead is because under certain unplanned for conditions a `while-loop` can become an infinite loop, i.e. potentially a race condition and it's much harder/more annoying to debug. I got told that by someone who's code I respect once but didn't dwell on it. So I always refactor to `for-loop` if I can. obviously not really possible if you want to break inside the loop unless language allows `break` in `for-loops`. – wide_eyed_pupil Aug 06 '15 at 11:23
  • @Voo equivalent? `while(..){..}` != `do {..} while(..)`, since the do-while is guaranteed to run at least once! – Martin Pfeffer Mar 20 '17 at 03:04
  • @MartinPfeffer I'll keep that in mind for the time when `true` starts evaluating to false. – Voo Mar 20 '17 at 10:51
  • 1
    You should email this page to your professor :) – Kellen Stuart May 01 '18 at 22:00
  • Your teacher is misinformed, or indeed uninformed. This attitude is common in academia, but non-existent out here in the real world. It is simply not the case that festooning your code with additional booleans or other state variables is superior in any way to using `break`, and there are good formal arguments to be made *against* additional state. The argument from Dijkstra does not hold. – user207421 Dec 03 '19 at 11:37

21 Answers21

230

I wouldn't say it's bad - but equally I would normally at least look for an alternative.

In situations where it's the first thing I write, I almost always at least try to refactor it into something clearer. Sometimes it can't be helped (or the alternative is to have a bool variable which does nothing meaningful except indicate the end of the loop, less clearly than a break statement) but it's worth at least trying.

As an example of where it's clearer to use break than a flag, consider:

while (true)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        break;
    }
    actOnInput(input);
}

Now let's force it to use a flag:

boolean running = true;
while (running)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        running = false;
    }
    else
    {
        actOnInput(input);
    }
}

I view the latter as more complicated to read: it's got an extra else block, the actOnInput is more indented, and if you're trying to work out what happens when testCondition returns true, you need to look carefully through the rest of the block to check that there isn't something after the else block which would occur whether running has been set to false or not.

The break statement communicates the intent more clearly, and lets the rest of the block get on with what it needs to do without worrying about earlier conditions.

Note that this is exactly the same sort of argument that people have about multiple return statements in a method. For example, if I can work out the result of a method within the first few lines (e.g. because some input is null, or empty, or zero) I find it clearer to return that answer directly than to have a variable to store the result, then a whole block of other code, and finally a return statement.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    I agree it's not the first tool I reach for, but it just seemed to take care of the problem so cleanly, and I do like clean code. – JHarnach Jul 27 '11 at 19:56
  • Are things like this reasons to extract some of the code from (or around) the loop and place it in external methods, allowing for (literal) early returns? – Clockwork-Muse Jul 27 '11 at 20:53
  • 3
    @X-Zero: Yes, sometimes. If you can turn the "break" into a "return" that's often goodness... although you might still end up with a `while (true)` – Jon Skeet Jul 27 '11 at 20:54
  • I actually like the example you posted more. I'm in different on the while vs do while part, but here your use of break looks fine and still clear to the reader what's happening. +1 – JHarnach Jul 27 '11 at 20:55
  • 2
    It is actually not that hard to "clean up the clutter" in the non-break version: just do `if( !(stop = condition ) ){ dostuff; }`, in fact, if the condition is complicated enough, putting `stop = condition;` (or `running = condition;`) on a line by itself, and reusing the value thereafter might actually improve readability. – trutheality Jul 27 '11 at 21:19
  • 24
    @trutheality: I prefer most of my code to be as unindented as possible though. And a condition with a compound assignment feels more complicated to me. – Jon Skeet Jul 27 '11 at 21:26
  • 1
    I always try to make assignments be on their own line, and I do this across many languages. It makes the code clearer (changing the state of the system is an _important_ thing) and it also helps a lot if I have to attach a debugger or other such tool (a trick I learned from John Ousterhout). – Donal Fellows Jul 28 '11 at 08:22
  • 1
    @Donal: I usually avoid compound assignments *other* than for the very common `while ((line = reader.ReadLine()) != null)` pattern. – Jon Skeet Jul 28 '11 at 08:27
  • 1
    I don't even like that one particularly, TBH. Not that it comes up that often, thankfully. – Donal Fellows Jul 28 '11 at 11:03
  • @Donal: I personally like encapsulating that pattern in an iterator, but where it's tricky to do that, it's a familiar enough pattern that I don't mind it. – Jon Skeet Jul 28 '11 at 11:10
  • I disagree with this. A condition can tell you what's going on upfront without having to read the code (useful if you are skimming). Wouldn't while(price < priceDiscountThreshhold) tell you more than while(true) ? – Razor Aug 03 '11 at 03:21
  • 4
    @Vince: Yes, and that's great *if you can express the condition easily at the start of the loop*. But sometimes you can't - and that's the situation we're talking about. Please note the first couple of sentences of my answer. – Jon Skeet Aug 03 '11 at 05:20
  • 7
    @Ismail: I hope not. Posts should be judged solely on their content, not on the author. Heck, I'd even downvote an Eric Lippert post if I felt it was inaccurate/unhelpful. That hasn't happened yet though :) – Jon Skeet Aug 04 '11 at 10:15
  • 2
    The more code from other people one has had to read in his life, the more one will +1 this answer. (And the other way around.) – TheBlastOne Aug 10 '11 at 22:55
102

AFAIK nothing, really. Teachers are just allergic to goto, because they heard somewhere it's really bad. Otherwise you would just write:

bool guard = true;
do
{
   getInput();
   if (something)
     guard = false;
} while (guard)

Which is almost the same thing.

Maybe this is cleaner (because all the looping info is contained at the top of the block):

for (bool endLoop = false; !endLoop;)
{

}
sam1370
  • 335
  • 2
  • 18
El Marcel
  • 1,767
  • 1
  • 10
  • 11
  • 4
    I like your suggestions since the terminating condition is much more visible. That means when reading the code you will sooner get a understanding of what it is trying to do. I would never use an infinite loop but use your two versions frequently. – Sled Jul 27 '11 at 20:02
  • 4
    The consensus is that a flag is better than break largely because it expresses intent? I can see that to be beneficial. All solid answers, but I'll mark this as accepted. – JHarnach Jul 27 '11 at 20:09
  • 21
    Both of these still suffer from the rest of the loop being polluted (in some situations at least) by having to keep going to the end of the body of the loop *even if you know you're breaking*. I'll put an example in my answer... – Jon Skeet Jul 27 '11 at 20:17
  • You could just put an if at the end like in your example. I actually used to be allergic to this kind of construct because I always associated loops with iterators and incrementing values, but now I see the value of the declaration of the loop var and the check being right next to the FOR. It's tidy, it's outside the braces. It's not always the best solution, but useful in some cases. – El Marcel Jul 27 '11 at 21:29
  • 9
    I like Jon Skeet's answer better. Also, while (true) {} is MUCH better than do {} while(true) – aaaa bbbb Jul 27 '11 at 21:38
  • haha, "true" :) they work identically anyway. – El Marcel Jul 27 '11 at 21:45
  • Or just use a function: while(getSomeInput()), instead of break use return. – Wedge Jul 27 '11 at 23:20
  • 2
    I hate that Dijkstra ever wrote that GoTo article. While GoTo certainly can was often was abused in the past doesn't mean you shouldn't ever use it. Also, Exit For, Break, Exit While, Try/Catch are all just specialized forms of Goto. Gotos can often make code more readable. And yes I'm aware that anything can be done without Goto. That doesn't mean it should. – Kibbee Jul 28 '11 at 01:39
  • @Kibbee: the list of specialized forms of goto goes further: if, for-loop without break, while-loop without break, break, continue, function calls, exceptions, .... If you remove all forms of hidden goto, I think you'd be left with a language that isn't Turing complete. – Lie Ryan Jul 28 '11 at 02:29
  • 1
    @Lie Ryan: Exactly, you can put lipstick on a pig, but it's still a pig. I've seen enough code (good and bad) in my day to know that Goto is neither sufficient or necessary for bad code. Even in old Basic, there were no function calls just GOSUB, which was very basic advance over GoTo, and that ON ERROR GoTo was the only error handling mechanism in VB all the way until it turned into VB.Net – Kibbee Jul 28 '11 at 12:36
  • if you work in a low memory "environment", it's better to avoid creating variables and condition checks... – kokbira Jul 28 '11 at 18:15
  • 1
    GOTOs are bad? The Assembly/Machine Language code that our programs turn into is riddled with the equivalent of GOTO. – oosterwal Jul 28 '11 at 23:06
  • Your second example can be shortened to `for (;;)` -- which is in fact the usual way to do this in some languages (e.g. C++) – Billy ONeal Aug 02 '11 at 16:05
  • Yeah, sure but you've still got to put that code somewhere. I was trying to show that the for struct can be (ab)used for more than iterators and fixed number counting. – El Marcel Aug 03 '11 at 01:13
  • Shorter would be `guard = condition` :-) – caylee Oct 24 '17 at 07:01
40

Douglas Crockford had a remark about how he wished JavaScript contained a loop structure:

loop
{
  ...code...
}

And I don't think Java would be any worse for having a loop structure either.

There's nothing inherently wrong with while(true) loops, but there is a tendency for teachers to discourage them. From the teaching perspective, it's very easy to have students create endless loops and not understand why the loop isn't ever escaped.

But what they rarely mention is that all looping mechanisms can be replicated with while(true) loops.

while( a() )
{
  fn();
}

is the same as

loop
{
  if ( !a() ) break;
  fn();
}

and

do
{
  fn();
} while( a() );

is the same as:

loop
{
  fn();
  if ( !a() ) break;
}

and

for ( a(); b(); c() )
{
  fn();
}

is the same as:

a();
loop
{
  if ( !b() ) break;
  fn();
  c();
}

As long as you can set up your loops in a way that works the construct that you choose to use is unimportant. If it happens to fit in a for loop, use a for loop.

One last part: keep your loops simple. If there's a lot of functionality that needs to happen on every iteration, put it in a function. You can always optimize it after you've got it working.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • 2
    +1: There are additional complexities with `for` loops when `continue` statements are involved, but they're not a major extension. – Donal Fellows Jul 28 '11 at 08:15
  • I usually use a for loop when there's a sequence I want to run across, and a while loop when there's a condition that I want to meet. This keeps the code more legible imo. – dascandy Jul 28 '11 at 13:34
  • 4
    Doesn't anyone write `for (;;) {` any more? (Pronounced "forever"). This used to be very popular. – Dawood ibn Kareem Dec 30 '14 at 22:52
  • @DawoodibnKareem [Not many](https://stackoverflow.com/questions/1401159/which-is-the-correct-c-sharp-infinite-loop-for-or-while-true), and that's a good thing! `for(;;)` is ugly and only ever caught on in the first place because [some really terrible early C compilers were too stupid to properly optimise the condition out of `while(true)`](http://www.flounder.com/exceptions.htm). Thankfully we now live in an age where readability trumps hacker-borne elitist esotericism, though we are yet to live in an age where the simple elegance of `loop` has been truly appreciated and taken to heart. – Pharap Sep 12 '22 at 11:20
20

Back in 1967, Edgar Dijkstra wrote an article in a trade magazine about why goto should be eliminated from high level languages to improve code quality. A whole programming paradigm called "structured programming" came out of this, though certainly not everyone agrees that goto automatically means bad code.

The crux of structured programming is essentially that the structure of the code should determine its flow rather than having gotos or breaks or continues to determine flow, wherever possible. Similiarly, having multiple entry and exit points to a loop or function are also discouraged in that paradigm.

Obviously this is not the only programming paradigm, but often it can be easily applied to other paradigms like object oriented programming (ala Java).

Your teachers has probably been taught, and is trying to teach your class that we would best avoid "spaghetti code" by making sure our code is structured, and following the implied rules of structured programming.

While there is nothing inherently "wrong" with an implementation that uses break, some consider it significantly easier to read code where the condition for the loop is explicitly specified within the while() condition, and eliminates some possibilities of being overly tricky. There are definitely pitfalls to using a while(true) condition that seem to pop up frequently in code by novice programmers, such as the risk of accidentally creating an infinite loop, or making code that is hard to read or unnecessarily confusing.

Ironically, exception handling is an area where deviation from structured programming will certainly come up and be expected as you get further into programming in Java.

It is also possible your instructor may have expected you to demonstrate your ability to use a particular loop structure or syntax being taught in that chapter or lesson of your text, and while the code you wrote is functionally equivalent, you may not have been demonstrating the particular skill you were supposed to be learning in that lesson.

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
Jessica Brown
  • 8,222
  • 7
  • 46
  • 82
  • 2
    Here is [Edsger Dijkstra's paper](https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf). It's a good read. – Roy Prins Apr 27 '18 at 20:08
14

The ususal Java convention for reading input is:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String strLine;

while ((strLine = br.readLine()) != null) {
  // do something with the line
}

And the usual C++ convention for reading input is:

#include <iostream>
#include <string>
std::string data;
while(std::readline(std::cin, data)) {
  // do something with the line
}

And in C, it's

#include <stdio.h>
char* buffer = NULL;
size_t buffer_size;
size_t size_read;
while( (size_read = getline(&buffer, &buffer_size, stdin)) != -1 ){
  // do something with the line
}
free(buffer);

or if you're convinced you know how long the longest line of text in your file is, you can do

#include <stdio.h>
char buffer[BUF_SIZE];
while (fgets(buffer, BUF_SIZE, stdin)) {
  //do something with the line
}

If you're testing to see whether your user entered a quit command, it's easy to extend any of these 3 loop structures. I'll do it in Java for you:

import java.io.*;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;

while ((line = br.readLine()) != null  && !line.equals("quit") ) {
  // do something with the line
}

So, while there certainly are cases where break or goto is justified, if all you're doing is reading from a file or the console line by line, then you shouldn't need a while (true) loop to accomplish it -- your programming language has already supplied you with an appropriate idiom for using the input command as the loop condition.

Ken Bloom
  • 57,498
  • 14
  • 111
  • 168
  • In fact, if you're using a `while (true)` loop instead of one of these conventional input loops, you might be forgetting to check for the end of the file. – Ken Bloom Jul 28 '11 at 03:57
  • 3
    You're accomplishing this effectively by stuffing the first part of the loop into the `while` conditional. In the final Java condition it's already getting fairly hefty, and if you had to do extensive manipulation to decide whether to continue or not, it may get quite long. You could split it out into a separate function, and that might be best. But if you do want it in one function, and there's nontrivial work to do before deciding whether to continue, `while(true)` may be best. – poolie Jul 28 '11 at 05:30
  • @poolie: Then it's probably best to use the read command as the loop condition (which checks for EOF), and check for your other conditions inside the loop as break statements. – Ken Bloom Jul 28 '11 at 11:36
  • 1
    For what it's worth, `gets()` isn't common convention. It's highly conducive to buffer overflows. `fgets(buffer, BUFFER_SIZE, file)` is much more like standard practice. – Dave Aug 02 '11 at 21:27
  • @Dave: I've now edited the answer to use `fgets`. – Ken Bloom Aug 02 '11 at 21:40
  • I think in C you really want to store the result of the read to see how much data you actually have... And please don't encourage `abusing namespace std;` in C++ :-) – Kerrek SB Jan 23 '12 at 04:24
  • @KerrekSB `fgets` doesn't work that way. From the manpage: "`gets()` and `fgets()` return `s` [the buffer that you passed in] on success, and NULL on error or when end of file occurs while no characters have been read." – Ken Bloom Jan 23 '12 at 04:27
  • @KenBloom: Oh, sorry, confused it with `fread`... errr, so how do you know if you got a whole line? I guess you have to check where the NULL is? – Kerrek SB Jan 23 '12 at 04:29
  • @KerrekSB: you call `getline`, which dynamically allocates its own memory. I'll update my answer. – Ken Bloom Jan 23 '12 at 04:33
11

It's not such a terrible thing, but you need to take into consideration other developers when coding. Even in school.

Your fellow developers should be able to see the exit clause for your loop, at the loop declaration. You didn't do that. You hid the exit clause in the middle of the loop, making more work for someone else who comes along and tries to understand your code. This is the same reason that things like "break" are avoided.

That being said, you'll still see things like this in a LOT of code out there in the real world.

rfeak
  • 8,124
  • 29
  • 28
  • 5
    If the loop starts off with `while (true)` it's pretty obvious that there's going to be a `break` or `return` inside it, or that it will run for ever. Being straightforward is important, but `while(true)` isn't especially bad, by itself. Variables that have complex invariants across loop iterations would be an example of something that causes much more angst. – poolie Jul 28 '11 at 05:33
  • 5
    Try going three levels deep in a search and then somehow breaking out. The code is going to be much worse if you don't just return from that point. – dascandy Jul 28 '11 at 13:35
11

It's your gun, your bullet and your foot...

It's bad because you are asking for trouble. It won't be you or any of the other posters on this page who have examples of short/simple while loops.

The trouble will start at some very random time in the future. It might be caused by another programmer. It might be the person installing the software. It might be the end user.

Why? I had to find out why a 700K LOC app would gradually start burning 100% of the CPU time until every CPU was saturated. It was an amazing while (true) loop. It was big and nasty but it boiled down to:

x = read_value_from_database()
while (true) 
 if (x == 1)
  ...
  break;
 else if (x ==2)
  ...
  break;
and lots more else if conditions
}

There was no final else branch. If the value did not match an if condition the loop kept running until the end of time.

Of course, the programmer blamed the end users for not picking a value the programmer expected. (I then eliminated all instances of while(true) in the code.)

IMHO it is not good defensive programming to use constructs like while(true). It will come back to haunt you.

(But I do recall professors grading down if we did not comment every line, even for i++;)

jqa
  • 1,340
  • 6
  • 17
5

It's bad in the sense that structured programming constructs are preferred to (the somewhat unstructured) break and continue statements. They are, by comparison, preferred to "goto" according to this principle.

I'd always recommend making your code as structured as possible... although, as Jon Skeet points out, don't make it more structured than that!

Patrick87
  • 27,682
  • 3
  • 38
  • 73
4

According to my experience in most cases loops have the "main" condition to continue. This is the condition that should be written into while() operator itself. All other conditions that may break the loop are secondary, not so important etc. They can be written as additional if() {break} statements.

while(true) is often confusing and is less readable.

I think that these rules do not cover 100% of cases but probably only 98% of them.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • Well said. It's like using a doing a for loop with: while(true) {i++;...}. You are burying the loop condition inside the loop rather than in the 'signature'. – LegendLength Jan 07 '16 at 02:39
3

While not necessarily an answer as to why not to use while (true), I've always found this comic and accompanying author's statement a succinct explanation as to why to do while instead of do-while.

With regards to your question: There is no inherent problem with

while(true) {
   do_stuff();
   if(exit_time) {
      break;
   }
}

... if you know what you're doing and making sure that exit_time will at some point evaluate to true.

Teachers discourage you from using while(true) because until and unless you're at the point that you know exactly what you're doing, it's an easy way to make a critical mistake.

Shadur
  • 345
  • 3
  • 18
  • 1
    I think setting `exit_time = false; while(!exit_time) { execute_stuff(); }` and `do { execute_stuff(); } while(! exit_time );` are both much clearer than having an `if( condition ) { break; }` at the end of a loop with a `while(true)`. Breaks are short-circuits to loops -- perfectly fine when used as a short-circuit in the middle of a loop, but you should just evaluate a condition in the while statement vs having a break at the end of a loop. – dr jimbob Jul 29 '11 at 13:53
  • In regard to that comic: while do-while can't do all that while can do, do-while sometimes is better doing what do-while can do even that while can also do. – Theraot Feb 08 '14 at 03:28
2

You might just use a Boolean flag to indicate when to end the while loop. Break and go to were reasons for software being to hard to maintain - the software-crisis(tm) - and should be avoided, and easily can be too.

It's a question if you are pragmatic or not. Pragmatic coders might just use break in that simple situation.

But it's good to get the habbit of not using them, else you might use them out of habbit in unsuitable situations, like in complicated nested loops where readability and maintainability of your code becomes harder by using break.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 9
    Because keeping a boolean flag is probably no clearer, and may well be *less* clear, in my experience? – Jon Skeet Jul 27 '11 at 19:58
  • 3
    @Jon Skeet Well its a question of going with a good habbit or training yourself a bad one by using break. A bool called "running" is not clear to you? Its obvious, easy to debug, and as i mentioned before a good habbit is a good thing to keep. Where is the problem? – Daniel Leschkowski Jul 27 '11 at 20:00
  • 5
    A bool called running that then requires me to have an `if (running)` within the loop, indenting all the rest of the code when all I want is to exit the loop is definitely *less* clear to me than a simple break statement which states *exactly* what I want do. You seem to be considering using break as a bad habit *axiomatically* - I don't think of it as such. – Jon Skeet Jul 27 '11 at 20:07
  • 2
    Why would you have an if (running) within the loop? As with break at the end of loop you check if you want to break out and flip the flag instead of using break and use the flag in while(running) instead of while(true). I dont get your point, seriously. I would agree that a pragmatic coder might use break in certain situations, but i really dont get the comments you made under my suggestion – Daniel Leschkowski Jul 27 '11 at 20:15
  • 4
    You're assuming you don't need to do anything within the loop after you've determined whether or not to quit. For example, in the OP's situation he needs to ask for more input if he's not quitting. – Jon Skeet Jul 27 '11 at 20:16
  • 1
    As in the post of the op the ask for more is the loop as i understood. And in that particular situation a break is no more clear then a flag – Daniel Leschkowski Jul 27 '11 at 20:17
  • 1
    I've added an example to my answer to show exactly what I mean. And no, I'm not going to chat because I'm going doing various other things. Flitting from place to place doesn't work well with chat. – Jon Skeet Jul 27 '11 at 20:23
  • The "ask for more" is the final comment of the block - in other words, code to be executed *only if we haven't broken out of the loop*. – Jon Skeet Jul 27 '11 at 20:24
  • 1
    Though i wont use it, and though i wont use the break statement as i - personal opionion - think its not more complicated to read (as far as i concern, the code "speaks" clearly to me in both ways - with or without break), ill give you an upvote because i can see you have a point. Which - in my humble oppinion - i dont have to share, but understand that for some it might be the right solution. I for myself believe that good habbits should be trained and kept if there is no drawback. And i dont see any, but as you teach using break, you might lead beginners to misusage of break. – Daniel Leschkowski Jul 27 '11 at 20:58
  • 1
    A `break` statement means just that: exit the loop, nothing else. A boolean can be manipulated, checked, and set in multiple places, and people have to trace their interaction to see whether and when the loop does actually terminate. All else being equal, `break` is simpler. – poolie Jul 28 '11 at 05:35
  • What you seem to overlook are certain things like nested loops where break makes following the code more complicated, rather then making it easier as you seem to think break always does. And if you screw up your code by obfuscated usage of a flag, thats way another problem... – Daniel Leschkowski Jul 28 '11 at 07:17
  • Another reason for good habits is consistency. If you use a different style for small loops vs big loops it's just yet another thing to think about. – LegendLength Jan 07 '16 at 02:41
  • In the vast majority of cases, a `break` or `return` is cleaner and more efficient. If you use a flag like `bool running = true; while(running) { running = false; }`, then the CPU has to waste cycles going back to the start of the loop and testing the value of `running`. If you know that it's time to end the loop, don't waste cycles doing unncessary jumping and testing. If you know that it's time to end the loop, just tell the CPU to end it - that's exactly what `break;` means: the loop is finished, there is no more work to do, exit now please. – Pharap Sep 12 '22 at 11:53
2

There's no major problem with while(true) with break statements, however some may think its slightly lowers the code readability. Try to give variables meaningful names, evaluate expressions in the proper place.

For your example, it seems much clearer to do something like:

do {
   input = get_input();
   valid = check_input_validity(input);    
} while(! valid)

This is especially true if the do while loop gets long -- you know exactly where the check to see if there's an extra iteration is occurring. All variables/functions have appropriate names at the level of abstraction. The while(true) statement does is tell you that processing isn't in the place you thought.

Maybe you want different output on the second time through the loop. Something like

input = get_input();
while(input_is_not_valid(input)) {
    disp_msg_invalid_input();
    input = get_input();
}

seems more readable to me then

do {
    input = get_input();
    if (input_is_valid(input)) {
        break;
    }
    disp_msg_invalid_input();
} while(true);

Again, with a trivial example both are quite readable; but if the loop became very large or deeply nested (which means you probably should already have refactored), the first style may be a bit clearer.

dr jimbob
  • 17,259
  • 7
  • 59
  • 81
2

Maybe I am unlucky. Or maybe I just lack an experience. But every time I recall dealing with while(true) having break inside, it was possible to improve the code applying Extract Method to while-block, which kept the while(true) but (by coincidence?) transformed all the breaks into returns.

In my experience while(true) without breaks (ie with returns or throws) are quite comfortable and easy to understand.


  void handleInput() {
      while (true) {
          final Input input = getSomeInput();
          if (input == null) {
              throw new BadInputException("can't handle null input");
          }
          if (input.isPoisonPill()) {
              return;
          }
          doSomething(input);
      }
  }
gnat
  • 6,213
  • 108
  • 53
  • 73
2

I think that yes it is pretty bad... or at least, for many developers. It is symptomatic of developers that don't think about their loop conditions. Consequently there is error prone.

1

It's more of an aesthetics thing, much easier to read code where you explicitly know why the loop will stop right in the declaration of the loop.

Petey B
  • 11,439
  • 25
  • 81
  • 101
1

I would say that generally the reason it's not considered a good idea is that you are not using the construct to it's full potential. Also, I tend to think that a lot of programming instructors don't like it when their students come in with "baggage". By that I mean I think they like to be the primary influence on their students programming style. So perhaps that's just a pet peeve of the instructor's.

Paul
  • 948
  • 8
  • 17
1

To me, the problem is readability.

A while statement with a true condition tells you nothing about the loop. It makes the job of understanding it much more difficult.

What would be easier to understand out of these two snippets?

do {
  // Imagine a nice chunk of code here
} while(true);

do {
  // Imagine a nice chunk of code here
} while(price < priceAllowedForDiscount);
Razor
  • 17,271
  • 25
  • 91
  • 138
0

I use something similar, but with opposite logic, in a lot of my functions.

DWORD dwError = ERROR_SUCCESS;

do
{
    if ( (dwError = SomeFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }

    if ( (dwError = SomeOtherFunction()) != ERROR_SUCCESS )
    {
         /* handle error */
         continue;
    }
}
while ( 0 );

if ( dwError != ERROR_SUCCESS )
{
    /* resource cleanup */
}
Jim Fell
  • 13,750
  • 36
  • 127
  • 202
0

I guess using break to your teacher is like breaking a branch of tree to get the fruit,use some other tricks (bow the branch) so that you get the fruit and the branch is still alive.:)

Bimal Sharma
  • 134
  • 14
0

1) Nothing is wrong with a do -while(true)

2) Your teacher is wrong.

NSFS!!:

3) Most teachers are teachers and not programmers.

Pacerier
  • 86,231
  • 106
  • 366
  • 634
  • @Connell wait till your teacher hear's that! – Pacerier Aug 03 '11 at 19:41
  • 1
    I'm self taught on the programming front. All I have to judge by is my IT teacher in secondary school, who taught us to make websites using Dreamweaver in such a way that EVERYTHING was an absolutely positioned div... – Connell Aug 04 '11 at 09:43
  • @Connell up my post to show your agreement – Pacerier Aug 04 '11 at 09:53
  • 2
    "Those who can't do, teach." - That's a pretty big generalization don't you think? Should doctors, engineers, pilots, etc all be self taught since their instructors are incompetent according to you? – filip-fku Aug 05 '11 at 04:26
  • @filip-fku wow wow~ cool it cool it! – Pacerier Aug 05 '11 at 07:22
  • Sorry that came out more serious sounding that I intended! I just thought that sweeping generalization was not fair. Sure there are crappy teachers but there are also very good ones - like with any career path. – filip-fku Aug 05 '11 at 07:41
  • I didn't make the generalisation myself, it's a fairly common phrase, especially at my old college. Sorry if I offended anyone. See http://blogcritics.org/culture/article/those-who-cant-do-teach/. – Connell Aug 11 '11 at 15:56
0

It might be bad if your loop runs on a background thread, so when you close your application by terminating a UI thread, that piece of code will continue to execute. As others already said, you should always use some kind of check to provide a way for cancellation.

Dmitry
  • 73
  • 1
  • 8