break, continue and nested loops
The loops in the last lesson dutifully went around until their condition failed. But sometimes the job is done and there's no point going on, and sometimes you want to skip this round and go straight to the next. This lesson covers break and continue, and then a loop inside another loop.
1#include <stdio.h>2 3int main(void) {4 for (int n = 51; n <= 100; n++) {5 if (n % 7 == 0) {6 printf("Found it: %d\n", n);7 break;8 }9 }10 printf("Search over\n");11 return 0;12}
Found it: 56 Search over
We want the first multiple of 7 above 50. Once 56 turns up, that's enough: break ends the loop right away, and 57 to 100 are never tried.
break: stop the loop now
When break runs, the whole loop is over. The program jumps to the code after the loop, and whatever comes after break in the body doesn't run either.
break often goes with while (1). Since 1 is always true, this loop can't stop on its own: **its only way out is break**. Say you have $50 and each item costs $12. How many can you buy?
1#include <stdio.h>2 3int main(void) {4 int budget = 50;5 int spent = 0;6 int items = 0;7 while (1) {8 if (spent + 12 > budget) {9 break;10 }11 spent += 12;12 items++;13 }14 printf("Bought %d items for $%d\n", items, spent);15 return 0;16}
Bought 4 items for $48
Press Step and watch the fifth round: spent + 12 is 60, more than 50, so break leaves the loop, and spent += 12; doesn't run.
Tip: Whenever you write while (1), make sure the break is sure to be reached some day, or you have an infinite loop.
continue: skip this round
continue doesn't end the loop. It skips the rest of this round and moves on to the next one. In a for loop, the i++ still runs before the next round. This prints 1 to 10, skipping the multiples of 3:
1#include <stdio.h>2 3int main(void) {4 for (int i = 1; i <= 10; i++) {5 if (i % 3 == 0) {6 continue;7 }8 printf("%d ", i);9 }10 printf("\n");11 return 0;12}
1 2 4 5 7 8 10
How many lines does this print?
1#include <stdio.h>2 3int main(void) {4 for (int i = 1; i <= 5; i++) {5 if (i == 3) {6 continue;7 }8 if (i == 5) {9 break;10 }11 printf("%d\n", i);12 }13 return 0;14}
For i at 1 and 2, it prints as usual. At 3, continue skips the printf. At 4, it prints. At 5, break ends the loop before 5 is printed. That's 1, 2 and 4: three lines.
Take care with continue in a while loop: if i++ sits at the end of the body, continue skips it too, i never changes again, and you have an infinite loop. Change the variable before the continue, or use for instead.
A loop inside a loop
A loop body can hold another loop: a nested loop. Each time the outer loop goes around once, the inner loop runs all the way through, from start to finish:
1#include <stdio.h>2 3int main(void) {4 for (int i = 1; i <= 2; i++) {5 for (int j = 1; j <= 3; j++) {6 printf("i = %d, j = %d\n", i, j);7 }8 }9 return 0;10}
i = 1, j = 1 i = 1, j = 2 i = 1, j = 3 i = 2, j = 1 i = 2, j = 2 i = 2, j = 3
Two outer rounds, three inner rounds each time: six lines. Press Step and watch j start over at 1 again and again.
A nested loop can print a multiplication table. The outer i picks the row, the inner j picks the place in that row, and j only goes up to i:
1#include <stdio.h>2 3int main(void) {4 for (int i = 1; i <= 5; i++) {5 for (int j = 1; j <= i; j++) {6 printf("%dx%d=%-4d", j, i, i * j);7 }8 printf("\n");9 }10 return 0;11}
1x1=1 1x2=2 2x2=4 1x3=3 2x3=6 3x3=9 1x4=4 2x4=8 3x4=12 4x4=16 1x5=5 2x5=10 3x5=15 4x5=20 5x5=25
Notice where printf("\n") is: outside the inner loop but inside the outer one, so there is one new line at the end of each row.
Printing a triangle
The same idea with stars instead of numbers draws a shape. Row number row gets row stars:
1#include <stdio.h>2 3int main(void) {4 int height = 4;5 for (int row = 1; row <= height; row++) {6 for (int k = 1; k <= row; k++) {7 printf("*");8 }9 printf("\n");10 }11 return 0;12}
* ** *** ****
When drawing a shape, first work out how many characters each row needs and how that relates to the row number. Then write the condition of the inner loop.
break leaves one loop only
In a nested loop, break ends only the loop it is in. The outer loop carries on:
1#include <stdio.h>2 3int main(void) {4 for (int i = 1; i <= 3; i++) {5 for (int j = 1; j <= 3; j++) {6 if (j == 2) {7 break;8 }9 printf("i = %d, j = %d\n", i, j);10 }11 }12 return 0;13}
i = 1, j = 1 i = 2, j = 1 i = 3, j = 1
To end both loops as soon as you find something, use a variable as a flag: when the inner loop finds it, set the flag to 1 and break; at the end of each outer round, check the flag and break too if it is 1. This finds the first pair of numbers whose product is 12:
1#include <stdio.h>2 3int main(void) {4 int found = 0;5 for (int i = 1; i <= 9; i++) {6 for (int j = 1; j <= 9; j++) {7 if (i * j == 12) {8 printf("%d x %d = 12\n", i, j);9 found = 1;10 break;11 }12 }13 if (found) {14 break;15 }16 }17 return 0;18}
2 x 6 = 12
Delete the outer if (found) and run it again to see which extra lines appear.
Where a variable can be used
A variable declared inside curly braces can be used only inside those braces, and an i declared in the parentheses of a for can be used only in that loop. Use it after the loop and the program won't compile:
1#include <stdio.h>2 3int main(void) {4 for (int i = 1; i <= 3; i++) {5 int square = i * i;6 printf("%d\n", square);7 }8 printf("%d\n", i);9 return 0;10}
main.c: In function 'main':
main.c:8:20: error: 'i' undeclared (first use in this function)
8 | printf("%d\n", i);
| ^
main.c:8:20: note: each undeclared identifier is reported only once for each function it appears inThe compiler says 'i' undeclared: on line 8, i no longer exists. The same goes for square, and it is a fresh variable every round, so its value doesn't carry over from one round to the next. If you need a variable after the loop, declare it before the loop: write int i; ahead of the for, then for (i = 1; i <= 3; i++). Where a variable can be used is called its scope; lesson 9 covers it in detail.
Practice
Write the code, then press Check. A hint costs nothing; the answer is there when you need it.
First square over 200
✓Try the numbers one by one from 1, find the first one whose square is greater than 200, print it (15), then end the loop with break.
15
1#include <stdio.h>2 3int main(void) {4 for (int n = 1; n <= 100; n++) {5 6 }7 return 0;8}
Skip the multiples of 4
✓Add up 1 to 20, but skip the multiples of 4, using continue. Print the result, 150.
150
1#include <stdio.h>2 3int main(void) {4 int total = 0;5 for (int i = 1; i <= 20; i++) {6 7 total += i;8 }9 printf("%d\n", total);10 return 0;11}
Upside-down triangle
✓Use nested loops to print an upside-down triangle: 4 * on the first row, one fewer on each row, 1 on the last.
**** *** ** *
1#include <stdio.h>2 3int main(void) {4 int height = 4;5 6 return 0;7}
What you learned
breakends a loop right away;while (1)can only be left withbreak, so make sure it gets reached.continueskips the rest of this round and goes on to the next; in awhileloop, don't skip the line that changes the variable.- In a nested loop, the inner loop runs all the way through for each outer round; that's how the multiplication table and the triangle are printed.
- In a nested loop,
breakleaves one loop only; to end both, use a flag variable. - A variable declared inside curly braces or in the parentheses of a
forcan't be used outside them.