5.2. The for Statement#
The for statement executes a statement or a block of statements
while a specified Boolean expression evaluates to true. Such evaluation involves
comparing the local loop counter variable (an integer counter that increments/decrements over every loop)
to a preset value. Since the number of loops is controlled by comparing the counter with the preset value,
you need to specify the preset value to decide the number of times you want to run the code block when defining
a for loop statement.
5.2.1. For Statement Syntax#
for loops are usually favored for iteration because the
all the information about the local loop variable are available in one place at the top,
which helps quickly visualize the overall sequence in the loop.
The C# for loop statement syntax is:
for ( *initializer* ; *condition* ; *iterator* )
{
// code block (statements)
}
Let us practice in csharprepl or VS Code:
for (int i = 1; i <= 5; i++)
{
Console.WriteLine(i);
}
You can see that the for loop has four parts, a three-section semicolon-separated header
and a body:
Initializer: This section is a variable declaration statement that declares a
local loop variable(oriterator variableor the counter) and initialize it with an initial value.Condition: The condition section is a boolean expression that determines if the next iteration in the loop should be executed or should the loop be terminated. If it evaluates to true, the next iteration is executed; otherwise, the loop is exited.
Iterator: The iterator (iteration expression) section that defines what happens to the counter after each execution of the body of the loop. A common behavior is reassigning (increment or decrement) the value of the counter.
The body of the loop, which must be a statement or a block of statements.
In the example above, the initializer is i = 1, condition is i <= n,
and iterator is i++ (see arithmetic operators).
Note that the initializer section is executed only once, before entering the loop.
Also, the declared variable is local to the for loop heading and
the loop body and can not be accessed from outside the for statement.
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.
Header variation
The declaration of a for loop header is flexible. There may be several variables of the
same type initialized, separated by commas. Also, at the end of the for loop heading,
the iteration portion may include more than one expression, also 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 csharprepl to check.
5.2.1.1. Execution sequence#
For the execution sequence of for loops, note that the different parts of the heading are used at different times:
When starting the statement, the initialization is done, and then the test of condition (boolean expression).
After finishing the body and returning to the heading, the iteration operations are done, followed by the test.
5.2.2. break and continue Statements#
The basic syntax of the for statement is simplistic. Here we are using the
break and continue statements to learn the pragmatic coding practice of the for
loops by connecting to our understanding of conditional/selection statements.
When performing iteration, there will be times that you want to alter the code execution
sequence by skipping part or all of the iterations. If you only want to break out of
the enclosing loop, but not out of the whole method or the outer loop (in case of
nested looping), use a break statement
break;
in place of return, since return will break out the current method. With the break
statement, execution continues after terminating the enclosing iteration statement.
Note that the break and continue statements only make practical sense
inside of an if statement that is inside the loop. In the following examples,
you see a for statement with a break statement enclosed in a
conditional/selection statement.
Assuming that variable target already has a string value and variable arr is an array of
strings. With your knowledge about arr.Length and arr[i] from String (string), read
the following code:
bool found = false;
for (int i = 0; i < arr.Length; i++) // loop for arr.Length times
{
if (arr[i] == target) // if one of arr == targe
{
found = true; // set found to true
break; // break out of the enclosing loop
}
}
if (found) // if found == true (from the previous block)
{
Console.WriteLine("Target found at index " + i);
}
else
{
Console.WriteLine("Target not found");
}
When an element in arr is reached that matches target, execution breaks out
of the for loop and move on to the if (found) statement block below.
Now, observe an alternate implementation with a compound condition (Compound Boolean Expressions) 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");
}
As you can see, the code exit because the condition section of the if statement header
has an expression !found (C# Operator Types), meaning found is not true.
The shows that since break statements rely on the logic of the conditional statement,
if the condition can be embedded in the header of the loop, you don’t have to use break.
However, if you are designing a loop that has multiple exit criteria, using break statements
can make the code much less verbose in the header’s condition section, and hence easier to
follow because the if statement conditions and the immediate break action may be clearly
presented.
5.2.3. Nested for Loop#
There will be times when nested loops are are required for the problem scenario. A nested loop can look like this:
outer-Loop
{
// body of outer-loop
inner-Loop
{
// body of inner-loop
}
... ... ...
}
Continuing with our discussion on break, let’s say we are in a situation like the following:
for (....) {
// some statements of outer for loop
for (....) {
...
if (...) {
...
break;
}
...
}
// some statements of outer for look
}
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. As an example:
for (int i = 0; i <= 3; i++)
{
for (int j = 0; j <= 3; j++)
{
if (i == 2)
{
break;
}
Console.WriteLine("{0} -- {1}", i, j);
}
}
Can you determine the output of the preceding code? Try it in csharprepl or a test project
in your tests folder.
continue Statement
For completeness we mention the much less used continue statement:
continue;
A continue statement:
- does not break out of the whole loop statement.
- break/skips the execution of the rest of the body in the current enclosing loop iteration.
- starts the next enclosing loop iteration.
In the simplest situations, a continue statement just avoids an extra else clause.
It can considerably shorten code if the test is inside of complicated, deeply nested
if statements. As an example:
for (int i = 0; i <= 3; i++)
{
for (int j = 0; j <= 3; j++)
{
if (i == 2)
{
continue;
}
Console.WriteLine("{0} -- {1}", i, j);
}
}
Can you determine the output of the preceding code? Try it in csharprepl or a test project
in your tests folder.
5.2.4. Additional Loop Step Patterns#
The following examples were moved from 0503-for-examples to keep all for step patterns in one section.
5.2.5. Step in loop header#
i++ is a common pattern and it increments by 1. Also common in the iterator/step section of
the loop header is using assignment statement to control stepping:
i = i + k;
or the equivalent short-hand compound assignment operator:
i += k;
This means to increment the variable i by k.
Most C# binary operations have a similar variation. For instance
if op is +, -, *, / or %,
variable op= expression
means the same as
variable = variable op expression
For example
x *= 5;
is the same as
x = x * 5;
5.2.6. foreach Essentials#
This short section was consolidated from the previous standalone foreach page.
5.3. foreach Statement#
A C# foreach works like a for loop, except it does not use the header
(initializer, condition, and iterator) for conditional looping flow control. Instead,
the foreach loop iterates through each element in a given sequence or collection of data and
runs a set of instructions once for each of the elements. In other words, the
foreach loop is used exclusively to loop through elements in an array
(or other data sets).
In the case of for loop in C#, the local loop variable refers to the index of an
array whereas, in the case of a foreach loop, the loop variable refers to
the values of the array.
In for loop, the loop variable is of type int. The reason for this is,
here the loop variable refers to the index position of the array. For the foreach
loop, the data type of the loop variable must be the same as the
type of the values stored in the array. For example, if you have a string array,
then the loop variable must be of type string.
The syntax of the foreach loop is:
foreach (type variableName in arrayName)
{
// code block to be executed
}
A foreach statement only works with an object that holds a sequence or collection of data.
We will see many more kinds of sequences later. For now we can illustrate
with a string, which is a sequence of characters. Observe and test the
following two pieces of code in csharprepl to see how foreach
differs from the for statement.
Say you want to print out some Unicode/ASCII code
for certain characters. To achieve that using C# for loop, the code could look like:
> string str = "ABCabc";
> for (int i = 0; i < 6; i++)
{
Console.WriteLine("Unicode for {0} is {1}", i, (int)str[i]);
}
Unicode for 0 is 65
Unicode for 1 is 66
Unicode for 2 is 67
Unicode for 3 is 97
Unicode for 4 is 98
Unicode for 5 is 99
>
As you can see, with a for loop, you refer to the individual characters by its index
and then cast it to int:
(int)str[i]
Since strings are considered as arrays consisting of char type characters, we can loop
through a string using a foreach statement using type char and cast to print out
the underlying int Unicode value of each character. To achieve the same results using
the foreach loop, the code would look like the following (pay attention to the local
loop variable char ch; type is required as usual):
> string str = "ABCabc";
foreach (char ch in str) {
Console.WriteLine("Unicode for {0} is {1}.", ch, (int)ch);
}
Unicode for A is 65.
Unicode for B is 66.
Unicode for C is 67.
Unicode for a is 97.
Unicode for b is 98.
Unicode for c is 99.
As you can see, in a foreach loop, we do not rely on array indexing to refer to the
elements. Instead, we refer to the elements directly with the local loop variable (ch)
declared with the type (char in this case).
As you see in the preceding example, the foreach heading feeds us one
character from str each time through, using the name ch
to refer to it. Since any new variable name must be declared with a type in C#,
so ch is preceded in the heading by its type, char. Then we can use
ch inside the body of the loop.
``foreach`` vs. for loop
Some of the advantages/disadvantages of foreach over the for loop are:
foreach not involve variable setup (iterates over each element of the array).
foreach are more concise and readable than the indexing
forstatement.
The foreach loop does have some limitations: [1]
They don’t keep track of the index of the item.
They cannot iterate backwards. The loop can only go forward in one step.
If you wish to modify the array, the foreach loop isn’t the most suitable option.
The foreach loop cannot execute two-decision statements at once.
If you have explicit need to refer to the indices of the items in the sequence,
then a foreach statement does not work for you.
5.3.1. break in foreach#
With a foreach loop, which has no explicit continuation condition,
the break could 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");
}
Note that for the for and foreach loops, you could do all the same things
with while loops, which you will learn in subsequent chapters, but there
are many situations where foreach loops and for loops are more convenient
and easier to read.
{rubric} Footnotes
[1] For a discussion of C# for loop vs foreach loop, see Understanding What Is C# Foreach Loop