Nested loops
A runner is training for a race, and the coach has a plan for several days: three laps every day. In a notebook, the runner marks "day, lap" pairs: day 1, lap 1; day 1, lap 2; and so on. When the day's laps are done, the next day comes, and the lap count starts over.
Such a plan is a loop inside a loop. The outer loop goes through the days, and a nested loop goes through the laps of one day:
for (int day = 1; day <= 2; day++)
{
for (int lap = 1; lap <= 3; lap++)
{
Console.WriteLine(day + " " + lap);
}
}
// 1 1
// 1 2
// 1 3
// 2 1
// 2 2
// 2 3The expression day + " " + lap glues a number, a space and the second number into one string. Let's take apart what happens:
- The outer loop starts with
day = 1. - The inner loop runs
lapfrom1to3, and the program prints1 1,1 2,1 3. - The inner loop is done, and the outer one runs its step:
daybecomes2. - The inner loop starts over, with
lap = 1, and prints2 1,2 2,2 3. - The outer step gives
day = 3, the conditionday <= 2is false, and both loops are over.
The inner loop runs in full on every iteration of the outer one. That is why its body runs 2 * 3, which is six, times: the number of outer iterations multiplied by the number of inner ones.
Interviewers bring this up when they talk about how fast a program is. If both loops go through n values, the body runs n * n times: for n = 1000, that is already a million iterations.
The inner loop depends on the outer one
The inner loop's condition can use the outer loop's variable. That is how you draw a triangle of stars, where row number row has exactly row stars:
for (int row = 1; row <= 4; row++)
{
for (int k = 1; k <= row; k++)
{
Console.Write("*");
}
Console.WriteLine();
}
// *
// **
// ***
// ****Let's go step by step:
- The outer loop goes through the rows:
rowfrom1to4. - The inner loop prints stars with
Console.Write, and they all stay on one line. The conditionk <= rowgives as many stars as the row's number. Console.WriteLine()with empty parentheses stands in the outer loop, after the inner one, and ends the line.
This is how you solve tasks that need every pair of values: a multiplication table, every combination of two numbers.
break in a nested loop
break ends only the nearest loop, the one it stands in. If it is inside a nested loop, the outer loop runs the rest of its body after the inner loop and then moves on to its next iteration.
This is where the training analogy breaks down. The coach can cancel the whole plan at once, but break has no such power: from the inner loop it cancels only today's laps, and the next day still comes.
To leave both loops at once, you set up a bool flag variable and check it in the outer loop's condition. Let's find the first pair of numbers from 1 to 3 whose product is 6:
bool found = false;
for (int a = 1; a <= 3 && !found; a++)
{
for (int b = 1; b <= 3; b++)
{
if (a * b == 6)
{
Console.WriteLine(a + " " + b); // 2 3
found = true;
break;
}
}
}Let's see how both loops end:
- While no pair has been found,
foundisfalse, and the outer loop's condition depends only ona. - With
a = 2andb = 3, the product is6: the program prints2 3and storestrueinfound. breakends the inner loop.- The outer loop runs its step
a++and checks the condition:!foundis now false, and the outer loop ends too.
Without && !found, the outer loop would move on to a = 3 and print another pair, 3 2. Interviewers sometimes ask how to leave two loops at once, and a flag in the outer loop's condition is one of the answers.
Common mistake
The nested loop uses the same variable name as the outer one:
for (int i = 1; i <= 2; i++)
{
for (int i = 1; i <= 3; i++) // ✗
{
Console.Write(i);
}
}error CS0136: A local or parameter named 'i' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameterThe program does not compile. The inner loop stands inside the outer one, where the variable i already exists. A second declaration with the same name would make it unclear which i is meant, and C# forbids it. Give the inner loop's variable its own name, such as j.
Key points
- A nested loop runs in full on every iteration of the outer one: with 2 days of 3 laps, its body runs
2 * 3times. - The inner loop's condition can use the outer loop's variable.
breakends only the nearest loop; to leave both, check a flag in the outer loop's condition.- A nested loop's variable needs its own name: you cannot reuse the outer loop variable's name.