# `break`, `continue`, and Labels

### `break`, `continue`, and Labels

`break` leaves a loop.

```zig
var i: usize = 0;

while (i < 10) : (i += 1) {
    if (i == 5) break;
    std.debug.print("{d}\n", .{i});
}
```

This prints:

```text
0
1
2
3
4
```

When `i` becomes `5`, the loop ends.

`continue` skips the rest of the current iteration and starts the next one.

```zig
var i: usize = 0;

while (i < 10) : (i += 1) {
    if (i % 2 == 0) continue;
    std.debug.print("{d}\n", .{i});
}
```

This prints:

```text
1
3
5
7
9
```

In a `while` loop with a continue expression, `continue` still runs the continue expression.

```zig
while (i < 10) : (i += 1) {
    if (i < 5) continue;
    std.debug.print("{d}\n", .{i});
}
```

The update `i += 1` is still performed.

A loop can have a label.

```zig
outer: while (true) {
    while (true) {
        break :outer;
    }
}
```

The label is written before the loop name. `break :outer` leaves the loop named `outer`, not just the inner loop.

Labels are useful with nested loops.

```zig
const table = [_][3]u8{
    .{ 1, 2, 3 },
    .{ 4, 5, 6 },
    .{ 7, 8, 9 },
};

const target: u8 = 5;

var row: usize = 0;
var col: usize = 0;

search: for (table, 0..) |line, r| {
    for (line, 0..) |value, c| {
        if (value == target) {
            row = r;
            col = c;
            break :search;
        }
    }
}
```

Without the label, `break` would leave only the inner loop. With the label, it leaves the whole search.

`continue` can also use a label.

```zig
outer: for (0..3) |i| {
    for (0..3) |j| {
        if (j == 1) continue :outer;
        std.debug.print("{d},{d}\n", .{ i, j });
    }
}
```

The output is:

```text
0,0
1,0
2,0
```

When `j` is `1`, the program continues the outer loop.

A labeled `break` may give a value to a loop expression.

```zig
const data = [_]u8{ 3, 8, 13, 21 };

const found = search: for (data, 0..) |x, i| {
    if (x == 13) break :search i;
} else null;
```

The value of `found` is `2`.

The label names the expression that receives the value.

The same idea works with blocks.

```zig
const x = blk: {
    const a = 10;
    const b = 20;
    break :blk a + b;
};
```

Here `break :blk` gives a value to the block.

For loops, `break` and `else` work together. The `else` branch runs only when the loop ends normally.

```zig
const found = for (data, 0..) |x, i| {
    if (x == target) break i;
} else null;
```

If `target` is found, `break i` gives the index. If the loop finishes without a break, the `else` branch gives `null`.

The same rule applies to `while`.

```zig
var i: usize = 0;

const found = while (i < data.len) : (i += 1) {
    if (data[i] == target) break i;
} else null;
```

A plain `break` gives no value. It is used when the loop result is not needed.

```zig
while (true) {
    if (done()) break;
}
```

A value break is used when the loop itself computes something.

```zig
const index = for (data, 0..) |x, i| {
    if (x == target) break i;
} else null;
```

Prefer plain `break` for control flow. Prefer value `break` when the loop is naturally a search, selection, or computation.

Exercise 3-21. Write a loop that stops when it finds zero.

Exercise 3-22. Write a loop that skips negative numbers and prints the rest.

Exercise 3-23. Write nested loops that search a two-dimensional array.

Exercise 3-24. Rewrite the nested search using a labeled `break`.

