do-while
Chapter Twenty-Nine
Syllabus topic 1, "Control Flow: Statements and Blocks, If-Else, Else-If, Switch, Loops- While and For Loops Do-while, Break and Continue, Goto and Labels"
Pages 137 to 140 of 222
In one line
do statement while (condition); runs the statement first and tests afterwards, so the body always runs at least once.
The form
do
statement
while (condition);The body runs. Then the condition is tested. If it is non-zero, the body runs again. The semicolon at the end is part of the statement and is not optional.
#include <stdio.h>
int main(void)
{
int i = 1;
do {
printf("%d ", i);
i++;
} while (i <= 5);
printf("\n");
int n = 0;
int count = 0;
do {
count++;
} while (count < n);
printf("with n = %d the body still ran %d time(s)\n", n, count);
return 0;
}1 2 3 4 5
with n = 0 the body still ran 1 time(s)The second loop is the point. count < n was false before the loop began, and the body ran anyway, because a do-while tests afterwards. A while loop with the same condition runs zero times, which chapter 27 showed.
The three loops compared
while | for | do-while | |
|---|---|---|---|
| Condition tested | Before the body | Before the body | After the body |
| Minimum passes | 0 | 0 | 1 |
| Parts collected in the header | Condition only | All three | Condition only |
| Ends with a semicolon | No | No | Yes |
| Suits | An event | A known count | Something that must happen once |
All three are interchangeable in the sense that any loop can be written with any of them. Which one you choose tells the reader what kind of loop it is, and that is the only reason to prefer one.
The missing semicolon
#include <stdio.h>
int main(void)
{
int i = 1;
do {
printf("%d ", i);
i++;
} while (i <= 5)
printf("\n");
return 0;
}nosemi.c: In function ‘main’:
nosemi.c:10:21: error: expected ‘;’ before ‘printf’
10 | } while (i <= 5)
| ^
| ;
11 | printf("\n");
| ~~~~~~The compiler is looking for the semicolon that ends the do-while statement and finds a printf instead. Modern gcc is helpful about it: it points at the end of line 10, which is exactly where the semicolon belongs, prints the ; it wants on a line of its own, and then shows the printf that made it notice. An older compiler will simply report a syntax error on line 11, which is why chapter 5 said an error is reported where the parser got stuck rather than where the mistake is.
What a do-while is actually for: asking until the answer is usable
A while loop would need the reading code written twice, once before the loop and once inside it. A do-while needs it once.
#include <stdio.h>
int main(void)
{
int marks;
int attempts = 0;
do {
printf("Enter marks out of 100: ");
if (scanf("%d", &marks) != 1) {
printf("\nInput ended.\n");
return 1;
}
attempts++;
if (marks < 0 || marks > 100) {
printf("\n%d is not between 0 and 100. Try again.\n", marks);
}
} while (marks < 0 || marks > 100);
printf("\nAccepted %d after %d attempt(s).\n", marks, attempts);
return 0;
}do-while
150
-8
63Enter marks out of 100:
150 is not between 0 and 100. Try again.
Enter marks out of 100:
-8 is not between 0 and 100. Try again.
Enter marks out of 100:
Accepted 63 after 3 attempt(s).Read the shape, because it is the one to reuse: ask, check, and repeat while the answer is unusable. The scanf return is checked separately, so that a loop cannot spin for ever on input that has ended.
That last point matters. A validation loop with no escape when the input runs out is an infinite loop, and it is the commonest way a student's program hangs in a practical examination.
The menu shape
MU's Practical 2(b) asked for a menu-driven calculator, and chapter 26 gave the switch. A real menu repeats, and a menu must be shown at least once, so it is a do-while round a switch.
#include <stdio.h>
int main(void)
{
int choice;
do {
printf("1 greet\n2 count to three\n0 quit\n");
printf("Choice: ");
if (scanf("%d", &choice) != 1) {
printf("\nInput ended.\n");
return 1;
}
printf("\n");
switch (choice) {
case 1:
printf("Hello.\n");
break;
case 2:
for (int i = 1; i <= 3; i++) {
printf("%d ", i);
}
printf("\n");
break;
case 0:
printf("Goodbye.\n");
break;
default:
printf("%d is not on the menu.\n", choice);
break;
}
printf("\n");
} while (choice != 0);
return 0;
}1
2
9
01 greet
2 count to three
0 quit
Choice:
Hello.
1 greet
2 count to three
0 quit
Choice:
1 2 3
1 greet
2 count to three
0 quit
Choice:
9 is not on the menu.
1 greet
2 count to three
0 quit
Choice:
Goodbye.case 0 prints its goodbye and the loop condition then ends the loop. Using break in case 0 to try to leave the loop would not work: a break inside a switch leaves the switch, not the loop around it. Chapter 30 is exactly that trap.
The do { } while (0) idiom
You will meet this and it is worth recognising once:
#define SWAP(a, b) do { int t = (a); (a) = (b); (b) = t; } while (0)A macro that expands to several statements has to behave as one statement, so that if (x) SWAP(p, q); else ... works. A bare block would leave the semicolon at the call site dangling; do { ... } while (0) runs once and swallows the semicolon. It is not a loop. It is the only way to write a multi-statement macro safely, and chapter 22's advice still holds: prefer a function.
do-while
What this does NOT mean
A do-while is not a while written backwards. The difference is real: the body runs before the first test, so it always runs at least once.
The semicolon is not optional. It is the only control structure in C that ends with one.
while (condition); on its own is not a do-while. It is a while loop with an empty body, which is chapter 23's stray-semicolon bug.
A do-while does not guarantee valid input. It guarantees one pass. Making the input valid is the condition's job, and handling input that has ended is yours.
break inside a switch inside a do-while does not leave the loop. It leaves the switch.
Quick revision
do statement while (condition);tests after the body, so the body always runs at least once.- The trailing semicolon is required. It is the only loop that needs one.
whileandformay run zero times;do-whilemay not.- Use it when something must happen once: asking for input, showing a menu, a retry.
- Validation shape: ask, check, repeat while the answer is unusable, with an escape for input that ends.
- A menu is a
do-whileround aswitch, with 0 meaning quit. do { ... } while (0)in a macro is not a loop; it makes several statements behave as one.
Test yourself
1. How many times does this body run?
int i = 10;
do { printf("%d ", i); i++; } while (i < 5);Once. The body runs before the condition is tested, and the condition is false the first time.
2. What is the one syntactic feature that distinguishes do-while from the other loops?
The semicolon after the while clause.
3. Write a loop that asks for a positive number and keeps asking until it gets one.
do {
printf("Enter a positive number: ");
if (scanf("%d", &n) != 1) return 1;
} while (n <= 0);4. Why is a do-while the right loop for a menu?
Because the menu must be shown at least once before the user can choose anything, and then repeated for as long as they do not choose to quit.
5. In a do-while containing a switch, how do you leave the loop from inside a case?
Set the loop's condition variable so the test fails, or use a flag, or return from the function. A break leaves only the switch.
6. What is do { ... } while (0) used for?
do-while
To make a multi-statement macro behave as a single statement, so that it can be used as the body of an if without the semicolon at the call site causing a syntax error. It is not a loop.
What can be asked on this, and how to answer it
"Explain the do-while loop with syntax and an example." Give the syntax including the semicolon, say the condition is tested after the body so it runs at least once, and give a program where the condition is false from the start to prove it. Contrast with while in one line.
"Distinguish between while and do-while." while tests before the body and may run zero times; do-while tests after and always runs at least once. do-while ends with a semicolon. while suits a loop that may not need to run; do-while suits input validation and menus.
"Write a program to accept marks and validate them using a do-while loop." Give this chapter's validation program. Keep the scanf return check and say why: without it, input that has ended makes the loop spin for ever.
"Which loop is a post-test loop?" do-while. while and for are pre-test loops.
The rest of this subject
These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.