Problem overview
The program greets three students and then announces the start of class. The expected output is:
Hey, Andy
Hey, Mike
Hey, Mary
Let's start the class!
The buggy version prints the announcement after every greeting:
Hey, Andy
Let's start the class!
Hey, Mike
Let's start the class!
Hey, Mary
Let's start the class!
Approach
Both calls to Console.WriteLine sit between the braces of the foreach, so both run once per student. That is why the output alternates between a greeting and the announcement.
Ask of each statement whether it depends on the current student. The greeting does: it uses the loop variable student. The announcement doesn't, and it should happen once, after the last greeting. A statement like that goes after the closing brace of the loop, where the program flow arrives only when the loop is finished.
Step by step
- Leave the greeting in the loop.
Console.WriteLine("Hey, " + student);needsstudent, so it stays inside the braces. - Close the loop right after the greeting. Move the closing brace up so it comes immediately after that line.
- Put the announcement below the loop. Now
Console.WriteLine("Let's start the class!");is a separate statement that runs once, after the third greeting.
The solution in C#
string[] students = {"Andy", "Mike", "Mary"};
foreach (string student in students) {
Console.WriteLine("Hey, " + student);
}
Console.WriteLine("Let's start the class!");
The flow is: create the array, run the loop body for Andy, Mike and Mary in order, and then continue with the line after the loop. The blank line is only for readability. C# ignores it, and the closing brace is what ends the loop body.
Tracing both versions
In the buggy version, each pass through the loop body runs two statements: the greeting for the current student, and the announcement. Three passes give six lines, alternating between the two. In the fixed version, the three passes each run only the greeting, which gives three lines. After the third pass the loop ends, the flow moves to the next statement below the closing brace, and the announcement is printed. That makes four lines in total.
A good habit when you debug output like this is to count. The expected output has four lines and the buggy output has six, which tells you immediately that something inside the loop runs more often than it should.
Edge cases and common mistakes
- Fixing the symptom with a condition. You could try an
ifinside the loop to detect the last student, but that is more complicated and easier to get wrong. Moving the statement is the simple fix. - Dropping the semicolon or the brace. Each statement ends with
;, and an unclosed brace makes the compiler report an error at the end of the file. - Putting the announcement above the loop. That prints it first instead of last. The expected output has it at the end, so it has to come after the closing brace.
- A different number of students. The fixed code prints one greeting per element, so a longer array gives more greeting lines and still a single announcement at the end. An empty array prints only the announcement.
- Misplacing a brace while editing. If you move the closing brace without moving the announcement, you can end up with braces that no longer pair up. After the edit, check that each
{has its matching}.