CodingBison

Sometimes, an application needs to run in a loop to execute a task multiple times. As an example, if we have an array of paintings and we are looking for a specific painting, then we need to run in a loop and for each run, keep comparing the details of specific painting to that of the loop's current painting; we keep doing this until we find the painting we are looking for.

C provides three different constructs for looping: (1) while loop (2) do-while loop, and (3) for loop. The three loop variants behave differently. So, let us begin by providing a flow-chart that highlights their behavior:



Figure: Three types of C Loops

The while loop is fairly simple. The looping happens as long as a specified condition is true and we quit the loop when the condition becomes false. Naturally, after every round, we need to update the loop state (or the condition variable) so that we can re-check if the condition has become true; in the above example, updating the loop state could be as simple as incrementing a counter variable.

The do-while loop also has a similar format, except that the while clause sits at the very end of the loop block. The distinctive feature of this variant is that the looping block would get executed at least once. This happens because even if the condition is false, the program must run starting from "do" till the point where it reaches the "while" condition. For cases, where we need to run the loop for the first round, whether condition is met or not, we should consider deploying "do-while" method.

The "for" loop cleanly tucks different phases of looping in one expression: initialization, conditional-check, and update conditional variable. The first part of the for loop is the initialization (e.g., "counter=0"), the second part is the loop-termination (e.g., "counter < 3"), and the last part is updating the conditional variable (e.g., "counter++"). Note that both initialization and updating the loop state is done automatically by the for-loop. We just need to specify it in the for-expression.

For while and do-while loops, the above flow-chart shows that we do the task and then update the conditional variable, but the ordering can also be the other way around and should be dictated by the application logic -- it is possible that in some cases, we update the condition first and then do the task.

Before we proceed any further, let us now take a look at a pseudo-code for these three variants. Please note the semi-colon at the end of the do-while clause!

 /* A while loop */ 
 while (condition) {
     Do the task
     Update the loop state 
 }

 /* A do-while loop */
 do {
     Do the task
     Update the loop state 
 } while (condition);

 /* A for loop */
 for (initialize; check condition; update the loop state) {
     Do the task
 } 

Now that we have seen an overview of these three looping variants, it is time to put our learning to test. For that, we can use an example contains a 2-dimensional array such that each row contains a painting ID and its availability in a store. Next, the example prints both of these values for the array using all the three looping styles.

 #include <stdio.h>

 #define THE_LAST_SUPPER 1001
 #define CYPRESSES       1002
 #define POTATO_EATERS   1003

 int main () {
     int counter;
     int painting_array[3][2] = {
             {THE_LAST_SUPPER, 100}, 
             {CYPRESSES,       10}, 
             {POTATO_EATERS,   11},
     };

     printf("Let us print using a while loop\n");
     counter = 0;
     while (counter < 3) {
         printf("[i: %d] painting_number: %d Availability: %d \n", counter,
                 painting_array[counter][0], painting_array[counter][1]);
         counter++;
     }

     printf("\nLet us print using a do-while loop\n");
     counter = 0;
     do {printf("[i: %d] painting_number: %d Availability: %d\n", counter,
                 painting_array[counter][0], painting_array[counter][1]);
         counter++;
     } while (counter < 3);

     printf("\nLet us print using a for loop\n");
     for (counter = 0; counter < 3; counter++) {
         printf("[i: %d] painting_number: %d Availability: %d\n", counter,
                 painting_array[counter][0], painting_array[counter][1]);
     }
     return 0;
 }

Here is the output. As expected, the output is identical for all the three methods.

 $ gcc loops.c  -o loops
 $ 
 $ ./loops
 Let us print using a while loop 
 [i: 0] painting_number: 1001 Availability: 100 
 [i: 1] painting_number: 1002 Availability: 10 
 [i: 2] painting_number: 1003 Availability: 11 

 Let us print using a do-while loop 
 [i: 0] painting_number: 1001 Availability: 100 
 [i: 1] painting_number: 1002 Availability: 10 
 [i: 2] painting_number: 1003 Availability: 11 

 Let us print using a for loop 
 [i: 0] painting_number: 1001 Availability: 100 
 [i: 1] painting_number: 1002 Availability: 10 
 [i: 2] painting_number: 1003 Availability: 11 

Run till Infinity

Sometimes, however, we need to run a program forever in a loop. For example, a network program (say a web-server) may continuously wait for requests from other applications, an interactive program may continuously wait for user-input, or a network protocol may continuously wait for a handshake message from a new peer. Such programs need to keep running and hence, require a loop with a condition that should always evaluates to True! Of course, an infinite loop could also terminate if an error occurs or if we kill the program. But that would be a different story!

All of the above three loop variants can be easily made to run till infinity.

For the while and do-while loops, we can keep the while condition always True; we can do this using "while (1)", because "1" being non-zero is always true. For the for loop, we can skip providing any loop termination clause; we can do this using "for(;;)". With this change, there is no termination-condition and the loop will run happily forever!





comments powered by Disqus