For-Statement Syntax
We now introduce the last kind of loop syntax: for
loops.
A for
loop is an example of syntactic sugar: syntax that can simplify
things for the programmer, but can be immediately translated into an
equivalent syntax by the compiler. For example:
for (i = 2; i <= n; i++) {
sum = sum + i;
}
is exactly equivalent to this code similar to part of SumToN:
i= 2;
while (i <= n) {
sum = sum + i;
i++;
}
More generally:
for (
initialization ;
condition ; update )
{}
translates to
;
while (
condition )
{;
}
In the example above, initialization is i=2
, condition is i <= n
,
and update is i++
.
Why bother with this rearrangement? It is a matter of taste, but the heading:
for (i = 2; i <= n; i++) {
puts all the information about the variable controlling the loop
into one place at the top, which may help quickly visualize the overall
sequence in the loop. If you use this format, and get used to the
three parts you are less likely to forget the i++
than when it comes tacked on to the end of a while loop body, after all
the specific things you were trying to accomplish.
Although the for
loop syntax is very general,
a strongly recommended convention
is to only use a for
statement when all the control of variables
determining loop repetition are in the heading.
For example if a for
loop uses i
in the heading, i
can have a value assigned or
reassigned in the heading, but should not have its value modified
anywhere inside the loop body.
If you want more complicated behavior, use a while
loop.
A for
loop can also include variable declaration in the initialization,
as in:
for (int i = 2; i <= n; i++) {
sum = sum + i;
}
This is close, but not quite equivalent to:
int i = 2;
while (i <= n) {
sum = sum + i;
i++;
}
Variables declared in a for
loop heading are local to the
for
loop heading and body. The variable i
declared before
the while
statement above is still defined after the while
loop.
The two semicolons are always needed in the for
heading, but any of the
parts they normally separate may be omitted.
If the condition part is omitted, the condition is
interpreted as always true, leading to an infinite loop, that can only
terminate due to a return
or break statement in the body.
Note the different parts of the heading used at different times (consistent with the positions in the corresponding while loop):
When starting the whole statement, the initialization is done, and then the test.
After finishing the body and returning to the heading, the update operations are done, followed by the test.
Other variations
As in a regular local variable declaration,
there may be several variables of the
same type initialized at the beginning of a for
loop heading,
separated by commas. Also, at the end of the for
loop heading, the
update portion may include more than one expression, separated by commas.
For example:
for (int i = 0, j = 10; i < j; i = i+2, j++) {
Console.WriteLine("{0} {1}", i, j);
}
Guess what this does, and then paste it into csharp to check.
The comma separated lists in a for
statement heading
are mentioned here for completeness. Later we will find a situation
where this is actually useful.
Break and Continue
This section concerns special break and continue statements
that can only occur inside a loop (any kind:
while
, for
or foreach
).
The syntax is convenient in various circumstances, but not necessary. You are free
to use it, but for this course it is an optional extra:
You can already stop a loop in the middle with an if
statement
that leads to a choice with a return
statement.
Of course that forces you to completely leave the current function. If you only want to
break out of the innermost current loop, but not out of the whole function, use
a break statement:
break;
in place of return. Execution continues after the end of the whole innermost
currently running loop statement.
The break
and continue
statements only
make practical sense inside of an if
statement that is inside the loop.
Examples, assuming target
already has a string value and a
is an array of
strings:
bool found = false;
for (int i = 0; i < a.Length; i++) {
if (a[i] == target) {
found = true;
break;
}
}
if (found) {
Console.WriteLine("Target found at index " + i);
} else {
Console.WriteLine("Target not found");
}
When an element is reached that matches target
,
execution goes on past the loop with if (found)
….
An alternate implementation with a compound condition in the heading and no break
is:
bool found = false;
for (int i = 0; i < a.Length && !found; i++) {
if (a[i] == target) {
found = true;
}
}
if (found) {
Console.WriteLine("Target found at index " + i);
} else {
Console.WriteLine("Target not found");
}
With a foreach
loop, which has no explicit continuation condition,
the break
would be more clearly useful.
Here is a variant if you do not care about the specific location of the target:
bool found = false;
foreach (string s in a) {
if (s == target) {
found = true;
break;
}
}
if (found) {
Console.WriteLine("Target found");
} else {
Console.WriteLine("Target not found");
}
Using break
statements is a matter of taste. There is some advantage in reading
and following a loop that has only one exit criteria,
which is easily visible in the heading. On the other hand, in many situations,
using a break statement makes the code much less verbose, and hence easier to follow.
If you are reading through the loop, it may be clearer to have an immediate action
where it is certain that the loop should terminate.
All the modifiers about innermost loop are important in a situation like the following:
for (....) {
for (....) {
...
if (...) {
...
break;
}
...
}
}
The break statement is in the inner loop. If it is reached, the inner loop ends, but the inner loop is just a single statement inside the outer loop, and the outer loop continues. If the outer loop continuation condition remains true, the inner loop will be executed again, and the break may or may not be reached that time, so the inner loop may or may not terminate normally….
For completeness we mention the much less used continue
statement:
continue;
It does not break out of the whole loop:
It just
skips the rest of the body of the innermost current loop, this time through the loop.
In the simplest situations a continue
statement just avoids an extra else
clause.
It can considerable shorten code if the test is inside of complicated, deeply nested
if
statements.