C course menu
break, continue and goto in C
Learn how to control loops in C with break and continue, break inside switch, leaving nested loops with a flag or a function, and the limited, legitimate use of goto for cleanup in error handling.
break and continue change how a loop runs. C also has goto, which jumps to a label; it is rarely needed, but one pattern for it is common in real C code.
break#
break leaves the innermost loop (or switch) immediately:
int orders[] = {120, 450, 80, 990, 300};
int first_big = -1;
for (int i = 0; i < 5; i++) {
printf("checking %d\n", orders[i]);
if (orders[i] > 400) {
first_big = orders[i];
break;
}
}
printf("First order over 400: %d\n", first_big);checking 120
checking 450
First order over 400: 450continue#
continue skips the rest of the current repetition and goes to the next one. In a for loop, the update (i++) still runs:
for (int i = 1; i <= 10; i++) {
if (i % 3 == 0) continue;
printf("%d ", i);
}
printf("\n");1 2 4 5 7 8 10 Leaving nested loops#
break only leaves the innermost loop. Two clean ways to stop an outer loop:
#include <stdio.h>
/* 1. Put the loops in a function and return */
int find(int grid[3][3], int target, int *row, int *col) {
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
if (grid[r][c] == target) {
*row = r;
*col = c;
return 1;
}
}
}
return 0;
}
int main(void) {
int grid[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int r, c;
if (find(grid, 6, &r, &c)) printf("Found at row %d, column %d\n", r, c);
/* 2. Use a flag */
int found = 0;
for (int i = 0; i < 3 && !found; i++) {
for (int j = 0; j < 3; j++) {
if (grid[i][j] == 8) {
found = 1;
printf("8 is at %d,%d\n", i, j);
break;
}
}
}
return 0;
}Found at row 1, column 2
8 is at 2,1The function version uses pointers (int *row) to return the position; pointers are explained in Pointers.
goto#
goto label; jumps to label: in the same function. Jumping around freely makes code very hard to follow, so most code never uses it. One accepted use is cleanup on error: when a function acquires several resources and any step can fail, jumping to a shared cleanup section avoids repeating the cleanup code:
#include <stdio.h>
#include <stdlib.h>
int process(void) {
int result = -1;
int *data = malloc(100 * sizeof *data);
if (data == NULL) goto done;
FILE *f = fopen("missing-file.txt", "r");
if (f == NULL) goto free_data;
/* ... use f and data ... */
result = 0;
fclose(f);
free_data:
free(data);
done:
return result;
}
int main(void) {
printf("process returned %d\n", process());
return 0;
}process returned -1The file does not exist, so the function jumps to free_data, frees the memory and returns an error. This pattern is common in operating system and library code; Error Handling shows it in context.
Practice#
Practice exercise
Loop through the numbers 1 to 50. Skip numbers that are not divisible by 7, print the ones that are, and stop completely after printing the first one greater than 30.
Show solution
#include <stdio.h>
int main(void) {
for (int n = 1; n <= 50; n++) {
if (n % 7 != 0) continue;
printf("%d ", n);
if (n > 30) break;
}
printf("\n");
return 0;
}7 14 21 28 35 Key takeaway#
Finished this lesson?