Module 4, Part 1: More About Loops#

In this first part of Module 4 we continue exploring how to write Java programs with loops. We introduce a new form of loop: the “for” statement. We also discuss the “continue” statement to control the execution of a loop.

For Statement#

Besides the “while” statement and the “do-while” statement, Java provides a third form of looping construct, called the for statement (or “for loop”). A for loop can be a convenient alternative to a while loop in cases where the loop has the following characteristics:

  • there is an initialisation statement that we want to execute only once, before starting the loop;

  • there is a loop condition that must evaluate to true before executing the loop body (otherwise, the loop ends);

  • there is an update statement that we want to execute just at the end of the the loop body, and just before the loop condition is evaluated again.

The for statement has the following syntax:

1for (init_statement; bool_expr; update_statement) {
2    // Statements that are executed at each loop repetition
3}
4// Other statements can follow (optionally)

The behaviour of the for loop above corresponds to the following while loop: (NOTE: this correspondence is slightly inaccurate, as we will discuss below — but it is good enough for now)

1{
2    init_statement;
3    while (bool_expr) {
4        // Statements that are executed at each loop repetition
5        update_statement; // Executed just at the end of the loop body
6    }
7}
8// Other statements can follow (optionally)

When represented as a flowchart, the for statement (including an optional break statement) looks as follows — where the highlighted part (excluding the loop condition bool_expr) is the loop body. Whenever we spot the following pattern in a flowchart, we should consider using a for statement when writing the corresponding Java program.

Flowchart of "for" loop

Example 27 (Summing numbers using a for loop)

Suppose we need to write a program that asks the user to provide a positive number \(n\), and then computes the sum of all numbers between 1 and \(n\). (Also suppose that we do not know the algorithm that Carl Friedrich Gauss invented when he was a child.)

We can achieve the result with the following code:

 1var s = new java.util.Scanner(System.in);
 2s.useLocale(java.util.Locale.ENGLISH);
 3
 4System.out.println("Please write a positive number:");
 5var n = s.nextInt();
 6
 7var sum = 0; // Will be updated during the computation of the sum
 8for (var i = 1; i <= n; i = i + 1) {
 9    sum = sum + i;
10}
11System.out.println("The sum of all numbers from 1 to " + n + " is: " + sum);
12s.close();

The code above is equivalent to the following, which uses a while loop instead: (for clarity, the for loop above and the equivalent while loop below are highlighted)

 1var s = new java.util.Scanner(System.in);
 2s.useLocale(java.util.Locale.ENGLISH);
 3
 4System.out.println("Please write a positive number:");
 5var n = s.nextInt();
 6
 7var sum = 0; // Will be updated during the computation of the sum
 8{
 9    var i = 1;         // Initialisation statement of the 'for' loop
10    while (i <= n) {   // Loop condition of the 'for' loop
11        sum = sum + i; // Body of the 'for' loop
12        i = i + 1;     // Update statement of the 'for' loop
13    }
14}
15System.out.println("The sum of all numbers from 1 to " + n + " is: " + sum);
16s.close();

You can observe that the for loop is considerably shorter.

Remark 13 (Scopes)

In Example 27, in the code that uses the while loop, notice the curly brackets {} on lines 8 and 14: they delimit a scope, and any variable declared inside that scope is not visible outside of it. Consequently, the variable i declared on line 9 is usable between lines 10 and 14 — but it becomes non-existent on line 15.

You can see it for yourself: if you try to reference i outside its scope (e.g. if you try to print its value on line 15), Java will report an error: “Cannot find symbol: variable i. (Try it on the Java shell!)

This corresponds to what happens in the for loop above in Example 27: any variable declared in the initialisation statement of the for loop is usable inside the for loop body, and does not exist outside of it.

Tip

When writing for loops, it is quite common to increment an index variable, as shown in Example 27. Java provides short-hand notation for incrementing a variable: writing i++ is equivalent to writing i = i + 1. Therefore, the for loop in Example 27 could be written as:

1for (var i = 1; i <= n; i++) {
2    sum = sum + i;
3}

In a similar fashion, Java provides short-hand notation for decrementing a variable: writing i-- is equivalent to writing i = i - 1. For example, see the following program that prints a countdown:

for (var n = 10; n > 0; n--) {
    System.out.println("Countdown: " + n);
}
System.out.println("Launch!");

Example 28 (Nesting loops)

The body of a for loop can contain any statement — and therefore, a for loop can contain another for loop. This also applies to while and do-while loops.

For instance, consider the following code snippet, which contains two nested for loops:

  • the outer for loop increments the variable i, starting from 0, until it reaches the value 3, and

  • the inner for loop increments the variable j, starting from 0, until it reaches the value 2.

1for (var i = 0; i < 3; i++) {
2    System.out.println("i is now " + i);
3    for (var j = 0; j < 3; j++) {
4        System.out.println("    j is now " + j + ", while i is " + i);
5    }
6}

Try copy&pasting and executing this code snippet on the Java shell. Observe that the inner loop is executed 3 times, i.e., once every time the body of the outer loop is executed. The values of the variables i and j change accordingly.

The continue Statement#

The continue statement can be used in any Java loop (while, do-while, and for) to “skip” the rest of the current repetition of the loop body, and possibly “continue” with the next repetition (if the loop condition is still true). The flowcharts of while, do-while, and for loops with a continue statement are depicted in Fig. 14, Fig. 15, and Fig. 16 below.

Flowchart of "while" loop with "continue"

Fig. 14 Flowchart of a while loop with a continue statement, jumping directly to the next loop condition check.#

Flowchart of "do-while" loop with "continue"

Fig. 15 Flowchart of a do-while loop with a continue statement, jumping directly to the next loop condition check.#

Flowchart of "for" loop with "continue"

Fig. 16 Flowchart of a for loop with a continue statement, jumping directly to the update_statement — followed by the next loop condition check.#

Example 29 (A for loop with continue)

The following code snippet prints the numbers from 1 to 10 — and for each number, it reports whether the number is even and/or divisible by 3. Notice that the code snippet uses a continue statement (on line 7) to “skip” the part of the loop body which prints “The number is divisible by 3”.

 1for (var n = 1; n <= 10; n++) {
 2    System.out.println("Number: " + n);
 3    if ((n % 2) == 0) {
 4        System.out.println("    The number is even");
 5    }
 6    if ((n % 3) != 0) {
 7        continue; // Skip rest of the loop body, contine with next repetition
 8    }
 9    System.out.println("    The number is divisible by 3");
10}

Important

Observe that, in the flowchart of the for loop with continue (Fig. 16 above), the continue statement jumps to the execution of the update_statement, before checking the loop condition again.

This is why the translation from for into while loops outlined above and in Example 27 is not entirely accurate. More precisely:

  • if a for loop body does not use a continue statement, then the translation from for loop into while loop outlined above is correct;

  • otherwise, if a for loop body contains a continue statement, and we translate the for loop into the corresponding while loop as outlined above, then the continue statement would jump directly to the next loop condition check — without executing the update_statement!

(Try it yourself: translate the for loop in Example 29 into a while loop as explained above, and observe the different behaviour.)

Remark 14 (Using continue statements vs. program clarity)

The continue statement has drawbacks that are similar to those of the break statement (discussed in Remark 11): it can make the loop execution harder to understand. Therefore, the continue statement should be only used when really needed.

Concluding Remarks#

You should now have an understanding of how to execute one or more statements repeatedly, depending on the result of a boolean expression, by using a For Statement. hem.

References and Further Readings#

You are invited to read the following section of the reference book: (Note: they sometimes mention Java features that we will address later in the course)

  • Section 6.4 - “The for Statement”

Exercises#

Note

These exercises are not part of the course assessment. They are provided to help you self-test your understanding.

Exercise 24 (Does this loop terminate?)

The following code snippets contain some loops: read each one, and try to determine whether it terminates. To check whether your guess is correct, run the loop in the Java shell — and remember that you can interrupt the execution of a loop by pressing Ctrl+C.

  • for (var i = 0; i < 10; i++) {
        System.out.println("i == " + i);
    }
    
  • for (var i = 20; i > 10; i++) {
        System.out.println("i == " + i);
    }
    
  • for (var i = 20; i < 10; i++) {
        System.out.println("i == " + i);
    }
    

Lab and Weekly Assessments#

During the lab you can try the exercises above or begin your work on the weekly assessments below.

Note

As an exercise, you can try solving these assessments using for loops first, and then you could revise your solutions using while loops. For the submissions on DTU Autolab, feel free to choose the solutions you like best.

Important

01 - Multiples#

Edit the file Multiples.java provided in the handout, and write a program that reads from the console two inputs:

  • a number \(n\) (of type int), and

  • a number \(m\) (of type int).

Then, the program must print all multiples of \(n\), ranging from \(n \times 0\) to \(n \times m\) (inclusive).

For instance, here is a possible execution of the program: (the highlighted lines are the user’s input)

52
4
52 * 0 = 0
52 * 1 = 52
52 * 2 = 104
52 * 3 = 156
52 * 4 = 208

When you are done, submit the modified file Multiples.java on DTU Autolab.

Warning

The automatic grading on DTU Autolab includes some additional secret checks that test your submission with more inputs. After you submit, double-check your grading result on DTU Autolab: if the secret checks fail, then your solution is not correct, and you should fix it and resubmit.

02 - Sum and Mean#

Edit the file SumMean.java provided in the handout, and write a program that reads from the console:

  • first, a number \(n\) (of type int, that you can assume to be non-negative), and

  • then, \(n\) values of type double.

After reading such inputs, the program must print the sum of the given \(n\) values. Furthermore, if \(n \neq 0\), then the program must also print the mean of the given \(n\) values. Then, the program must end.

For instance, here is a possible execution of the program: (the highlighted lines are the user’s input)

4
1
2.0
3
4.0
The sum of the 4 given values is: 10.0
The mean of the 4 given values is: 2.5

When you are done, submit the modified file SumMean.java on DTU Autolab.

Hint

  • Your program can compute the sum of the \(n\) input values progressively, after it reads each value from the console.

  • Remember that, if we have a set of \(n\) input values \(x_1, \ldots, x_n\), then their mean \(\bar{x}\) is computed as:

    \[ \bar{x} \;=\; \frac{1}{n}\sum_{i = 1}^n x_i \]

Warning

The automatic grading on DTU Autolab includes some additional secret checks that test your submission with more inputs. After you submit, double-check your grading result on DTU Autolab: if the secret checks fail, then your solution is not correct, and you should fix it and resubmit.

03 - String Characters Repetition#

Edit the file Ssttrriinngg.java provided in the handout, and write a program that reads from the console two inputs:

  • a number of repetitions \(n\) (of type int), and

  • a whole line of characters (as a String).

Then, the program prints the input string by repeating each one of its characters \(n\) times.

For example, if the input is:

3
D T U

The program must print:

DDD   TTT   UUU

When you are done, submit the modified file Ssttrriinngg.java on DTU Autolab.

Important

If you create a scanner s and then call s.nextInt() followed by s.nextLine(), your program may read a number followed by an empty string: the reason is explained e.g. in this article.

To avoid the issue, you may read the number of repetitions \(n\) by using (instead of s.nextInt()):

var n = Integer.parseInt(s.nextLine());

Hint

You will need to use the String objects’ methods .length() and .charAt(...), described in Some Useful String Methods.

04 - Characters#

Edit the file Characters.java provided in the handout, and write a program that reads a whole line from the console, and then, for each character \(x\) belonging to that line, prints:

  • The character 'x' is an uppercase letter if \(x\) is AZ

  • The character 'x' is a lowercase letter if \(x\) is az

  • The character 'x' is a digit if \(x\) is 09

  • The character 'x' is a special symbol if \(x\) is one of: # ! + \

  • The character 'x' is not known if \(x\) none of the above

The program must keep reading lines and printing the descriptions of their characters (as explained above) until the standard input stream is closed (by pressing Ctrl+D — or, on Windows, Ctrl+Z and then ).

For example, if the line read from the console is the string Hej!, the program must print:

The character 'H' is an uppercase letter
The character 'e' is a lowercase letter
The character 'j' is a lowercase letter
The character '!' is a special symbol

When you are done, submit the modified file Characters.java on DTU Autolab.

Hint

  • This program will need to loop through all characters of each input line. Consider that the program may read an empty line from the console, i.e. a String object "" containing 0 characters.

  • You will need to use the String objects’ methods .length() and .charAt(...), described in Some Useful String Methods.

  • Remember that, in Java, we write the literal 'A' to represent the value (of type char) of the character A, 'B' for the value of character B, etc.

  • You can find the numerical values of Unicode characters here:

  • Observe that Java uses the numerical Unicode values to compare characters. So, for example: (try the following on the Java shell!)

    • the expression 'z' > 'a' produces true, because 'z' has Unicode value 122, while 'a' has Unicode value 97;

    • the expression 'D' >= 'F' produces false, because 'D' has Unicode value 68, while 'F' has Unicode value 70.

  • Remember that the backslash character \ must be escaped when it is written in a literal char or String. Therefore, to represent the Unicode character \, we must write the literal character '\\'.