Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there ever a need for a "do {...} while ( )" loop?

Tags:

c++

c

loops

People also ask

Do you need a do while loop?

The do while loop checks the condition at the end of the loop. This means that the statements inside the loop body will be executed at least once even if the condition is never true. The do while loop is an exit controlled loop, where even if the test condition is false, the loop body will be executed at least once.

Is do-while useless?

do-while is primarily "better" if you want to perform an action at least once, e.g. asking for input, or getting some random value until it fits into some constraint. You can do such an action by performing the action once outside a "regular" loop and looping from there, but it's just neater to use do-while .

Why does do-while exist?

“Do-while” loop consists of checking if condition is true AFTER the first instructions execution. This is the only reason to make it usable instead of classic “while”. If you're sure that something must go at least one time, then you can use it.


Yes I agree that do while loops can be rewritten to a while loop, however I disagree that always using a while loop is better. do while always get run at least once and that is a very useful property (most typical example being input checking (from keyboard))

#include <stdio.h>

int main() {
    char c;

    do {
        printf("enter a number");
        scanf("%c", &c);

    } while (c < '0' ||  c > '9'); 
}

This can of course be rewritten to a while loop, but this is usually viewed as a much more elegant solution.


do-while is a loop with a post-condition. You need it in cases when the loop body is to be executed at least once. This is necessary for code which needs some action before the loop condition can be sensibly evaluated. With while loop you would have to call the initialization code from two sites, with do-while you can only call it from one site.

Another example is when you already have a valid object when the first iteration is to be started, so you don't want to execute anything (loop condition evaluation included) before the first iteration starts. An example is with FindFirstFile/FindNextFile Win32 functions: you call FindFirstFile which either returns an error or a search handle to the first file, then you call FindNextFile until it returns an error.

Pseudocode:

Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
   do {
      process( params ); //process found file
   } while( ( handle = FindNextFile( params ) ) != Error ) );
}

do { ... } while (0) is an important construct for making macros behave well.

Even if it's unimportant in real code (with which I don't necessarily agree), it's important for for fixing some of the deficiencies of the preprocessor.

Edit: I ran into a situation where do/while was much cleaner today in my own code. I was making a cross-platform abstraction of the paired LL/SC instructions. These need to be used in a loop, like so:

do
{
  oldvalue = LL (address);
  newvalue = oldvalue + 1;
} while (!SC (address, newvalue, oldvalue));

(Experts might realize that oldvalue is unused in an SC Implementation, but it's included so that this abstraction can be emulated with CAS.)

LL and SC are an excellent example of a situation where do/while is significantly cleaner than the equivalent while form:

oldvalue = LL (address);
newvalue = oldvalue + 1;
while (!SC (address, newvalue, oldvalue))
{
  oldvalue = LL (address);
  newvalue = oldvalue + 1;
}

For this reason I'm extremely disappointed in the fact that Google Go has opted to remove the do-while construct.


It's useful for when you want to "do" something "until" a condition is satisfied.

It can be fudged in a while loop like this:

while(true)
{

    // .... code .....

    if(condition_satisfied) 
        break;
}

The following common idiom seems very straightforward to me:

do {
    preliminary_work();
    value = get_value();
} while (not_valid(value));

The rewrite to avoid do seems to be:

value = make_invalid_value();
while (not_valid(value)) {
    preliminary_work();
    value = get_value();
}

That first line is used to make sure that the test always evaluates to true the first time. In other words, the test is always superfluous the first time. If this superfluous test wasn't there, one could also omit the initial assignment. This code gives the impression that it fights itself.

In cases such like these, the do construct is a very useful option.