What a nested loop is
A nested loop is a loop inside another loop. The outer loop runs its body once per iteration, and each time it does, the inner loop starts from scratch and runs all of its iterations before the outer loop moves on. If the outer loop runs 5 times and the inner loop 10 times, the inner body runs 5 × 10 = 50 times.
Nested loops are the natural tool for anything with two dimensions: rows and columns of text, grids, tables, and every pair of elements in a collection. The next problems in this chapter use them to try all pairs by brute force.
Printing a rectangle
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 5; col++) {
Console.Write("*");
}
Console.WriteLine();
}
This prints 3 rows of 5 stars:
*****
*****
*****
Two console methods do the work. Console.Write prints its text and stays on the same line. Console.WriteLine() with no argument only ends the current line. Together they let the inner loop build one row, and the outer loop start the next.
Looping over a jagged array
A C# array of arrays, int[][], is called a jagged array. Each element is itself an int[], and the rows may have different lengths. A nested loop visits every value:
int[][] arr = { new[] {1, 2}, new[] {3, 4}, new[] {5, 6} };
for (int i = 0; i < arr.Length; i++) {
for (int j = 0; j < arr[i].Length; j++) {
Console.WriteLine(arr[i][j]);
}
}
This prints 1, 2, 3, 4, 5 and 6 on separate lines. Note that the inner loop checks arr[i].Length, the length of the current row, not arr.Length. In C# the length of an array is the property Length, with a capital L.
C# also has rectangular arrays, written int[,]. For those, Length is the total count of cells, and GetLength(0) and GetLength(1) give the number of rows and columns.
break in nested loops
A break stops only the loop it is directly inside.
break in the inner loop
for (int i = 0; i < arr.Length; i++) {
for (int j = 0; j < arr[i].Length; j++) {
if (arr[i][j] == 3) {
break;
}
Console.WriteLine(arr[i][j]);
}
}
It prints 1, 2, 5 and 6. When i is 1 and j is 0, the value is 3 and the inner loop ends. The outer loop then continues with i = 2, and row 2 prints in full. The 4 is skipped as well, because it sits after the 3 in the same row.
break in the outer loop
for (int i = 0; i < arr.Length; i++) {
if (arr[i][0] == 3) {
break;
}
for (int j = 0; j < arr[i].Length; j++) {
Console.WriteLine(arr[i][j]);
}
}
This prints only 1 and 2. At i = 1 the first value of the row is 3, and the break ends the outer loop, so rows 1 and 2 never print.
C# has no labelled break. To leave both loops from inside the inner one, move the loops into a method and use return, or set a flag that the outer loop checks. The Two Sum lesson uses the return approach.
The exercise, step by step
The task is to print a rectangle of stars with 5 rows and 10 columns.
- Outer loop. A
forloop withint rowfrom 0 whilerow < 5. It runs once per row. The body never readsrow; it only counts passes. - Inner loop. Inside it, a loop with
int colfrom 0 whilecol < 10. It runs 10 times for every pass of the outer loop. - Print a star. Inside the inner loop,
Console.Write("*"), so the 10 stars share a line. - End the row. After the inner loop's closing brace, but still inside the outer loop,
Console.WriteLine()moves to the next line.
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 10; col++) {
Console.Write("*");
}
Console.WriteLine();
}
The output is five lines of ten stars.
Common mistakes
- Putting
Console.WriteLine()inside the inner loop. Every star would end up on its own line, 50 lines in all. - Leaving it out. All 50 stars would print on one long line.
- Reusing the same variable name. C# does not let an inner loop declare a variable with the same name as one in the enclosing scope, so use
iandj, orrowandcol. - Using the wrong length. In a jagged array the inner bound is
arr[i].Length. Witharr.Lengththe loop can run past the end of a short row and throwIndexOutOfRangeException. - Expecting
breakto leave both loops. It leaves only the innermost one.
Key takeaways
- The inner loop restarts and finishes on every pass of the outer loop, so the total work is the product of the two counts.
- Print with
Console.Writeinside the inner loop andConsole.WriteLine()after it. - Use
arr[i].Lengthfor the inner bound of a jagged array. breakaffects only the loop it is in.