The Post-Test Loop in C
The last of the looping or iterating choices provided by the C programming language, the do..while loop, is presented here. As mentioned, it would not be difficult to use a while loop to solve all your repetition needs, but it is nice and sometimes cleaner, to use the diversity of other tools when they are offered. As long as you understand the differences, these are all tools you can use effectively.
Using the do..while Loop
Once you have looked at the while kinds of loops, you should see that it is easy to implement the do..while kind of loop. In fact, for the exercise, consider the same character counting condition using the do..while loop.
// in global constant area of program
const char PERIOD = '.';
// in function where loop is used (local)
int characterCounter = 0;
char testLetter;
// display a prompt
// function: printString
printString( "Enter a sentence ending with a period: " );
// start loop
do
{
// get first letter
// function: getChar
testLetter = getChar();
// check for letter is not a period
if( testLetter != PERIOD )
{
// increment the character counter
characterCounter++;
}
}
while( testLetter != PERIOD );
// end loop, when character is a period
// i.e., loop while character is not a period
The initialization for this segment sets characterCounter to zero. Consider the code. At least one character will have to be input, so the do . . while loop can be an appropriate one to use. If the character is not a period, the characterCounter will be incremented. If the character is a period, the characterCounter will not be incremented. The loop will continue until the end of the sentence indicated by the period, is found.
To review the loop, consider the parts of the loop that were presented in the first section.
- initializing condition: the character counter is set to zero
- condition to continue: the loop will continue while the input character is not a period
- updating action: the input process will bring in a new test letter with every iteration; note also that the character counter variable will be updated after all but the last iteration, but this variable is used for information later on - it does not affect the operation of the loop
You must keep track of these loop components. As long as you do, you will be able to write loops that work every time. You must also test your loops with various conditions to make sure you are getting the correct processing you need from them. You will be reading more about that later.
An easy mistake
Stop for a moment now, and take a second look at the code. There is a significant syntax condition of which you need to be aware. When you write a plain old while loop, the while statement starts the loop, and the last curly brace ends it, shown here.
while( counter < maxValues )
{
// code inside loop
}
There are no semicolons in the above code at all. Now consider the do . . while statement, shown here.
do
{
// code inside loop
}
while( counter < maxValues );
There is a semicolon after the do..while loop, because the while statement ends the loop block. In the while loop, a curly brace ended the statement, and curly braces do not need semicolons to indicate a complete statement.
However, since the do..while loop is ended with a while statement after the last curly brace, the code needs a semicolon to indicate the end of a complete statement (i.e., the loop). Do not forget this. It is very common for programmers to make either mistake. Sometimes they put a semicolon after the while loop statement at the beginning of the loop, as shown below.
while( counter < maxValues ); // BAD, BAD, BAD
{
// code inside loop
}
The above code is one example of how to write an infinite loop. The program will see the while statement, and test for counter < maxValues, which would presumably be true the first time through.
Then the program will see the semicolon, so it will go back to the beginning of the loop, which means it will go to the while and test the counter < maxValues, then it will see the semicolon, and then . . . well, you should get the idea. Nowhere in this process will counter be updated, so there is no chance of completing this loop.
The cool thing about computers is that they can execute this loop millions or possibly billions of times per second, but it is like running in circles at 200 miles per hour. You may be going fast, but you are not getting anywhere. Each time you run your program, it will proceed to the point of this while loop, and then it will stay there until you stop the program.
The alternative mistake is easier to catch. Here is an example of an incorrect do..while statement with the semicolon left off.
do
{
// code inside loop
}
while( counter < maxValues ) // missing semicolon here
This mistake will be caught by the compiler, which will complain that your code is missing a semicolon. Most people do not have too much trouble finding this. However, it is still better for you to do it right the first time instead of waiting for the compiler to set you straight.
On the menu
As mentioned earlier, the do..while loop is also handy for menu presentations. Consider the following pseudo code.
do
{
display menu choice 1
display menu choice 2
.
.
display menu choice N
prompt for user input
accept user input
if user choice is less than 1 or greater than N
{
display an error message, and tell user to try again<
pause the program so that user can read this message
}
}
while the user's choice is less than 1 or greater than N
Now consider a real example of this kind of loop.
// in function where loop is used (local)
int answer;
// start loop
do
{
// display choices
// function: printString
printString( "1. Add a file" );
printString( "2. Edit a file" );
printString( "3. Delete a file" );
printString( "4. Exit this menu" );
// display prompt, acquire input
// function: promptForInt
answer = promptForInt( "Enter selection: " );
// check for answer in range
if( ( answer < 1 ) || ( answer > 4 ) )
{
// display error message
// function: printString
printString("Entry Error: " );
printString("Selection must be 1, 2, 3, or 4" );
// hold for user to read
// function: promptForChar
promptForChar("Press any letter key"
+ " and ENTER to continue" );
}
}
while( ( answer < 1 ) || ( answer > 4 ) );
// loop while answer is outside of range
Remembering that the do . . while loop will always run through one iteration, the menu choices will be presented. If the user selects an appropriate number, than she will go on to the next action. However, if she selects an incorrect number, the code will advise her that she needs to enter the correct selection number. Then, after she enters a letter key, the loop will redisplay the menu choices, and wait for another user response. The do . . while loop may not be used very often, but it is handy when you have a condition that will always be run at least once. If there is any chance that one iteration could cause a problem, use one of the other loops.
Side note: Notice that the prompt for a letter key uses a promptForChar function but does not assign the result to anything. This is another example where there is no need for the result. The promptForChar was just holding up the error display until the user entered some letter and then pressed the ENTER key.
There is one more thing to mention before leaving the loop code introduction area. Just like the if and other branching statements, it is legal in C to go without the curly braces if you have only one line of code to repeat.
Here is an example using the for loop.
// in global constant area of program
const char SPACE = ' ';
// in function where loop is used (local)
int counter;
for( counter = 0; counter < numSpaces; counter++ )
printChar( SPACE );
However, due to both the loss in readability of the code, and the potential for adding significant bugs to the code when it is modified, it is not worth going without the curly braces. It is so much clearer and safer to implement the following code that you should always follow Nike's motto - "Just Use Curly Braces".
// in global constant area of program
const char SPACE = ' ';
// in function where loop is used (local)
int counter;
for( counter = 0; counter < numSpaces; counter++ )
{
// display space
// function: printChar
printChar( SPACE );
}
The Process of Repetition, Completed
In this topic, you have seen the same thing you saw in previous topics, but using tools that expand your capabilities. The while loop can be implemented as itself, or in the packaged form of the for loop. The do..while loop has its own characteristics. While either the while or for loops can be used for most looping conditions that require tests before the operations (i.e., pre-tests), the do..while loop is very helpful if you are sure that you want your loop to iterate at least once (i.e., post test). Other than that, they are all three ways to make a segment of code repeat.
Watch the following video to view and practice with do..while loops.