For Loops
How do we write counted repetition on one line, and build tables and patterns with it?
By the end of this lecture you will be able to
- Write a
forloop and convert it to an equivalentwhile - Count up, down and in steps
- Explain the scope of the loop variable and choose between
forandwhile - Trace nested loops with the debugger and print patterns with them
- Check whether a number is prime and use
breakandcontinue - Avoid the semicolon trap and changing the loop variable inside the loop
In this lecture
- for puts initialise, test and update on one line
- Every for loop is a while loop, neatly arranged
- Counting can go up, down or in any step we want
- A loop variable declared in for does not outlive the loop
- for suits a known count, while suits ending on an event
- A sum starts at 0, a product starts at 1
- A times table is one loop and one print line
- In a nested loop, the inner loop finishes completely for each outer iteration
- print stays on the line and println ends it, so together they make a grid
- A rectangle: the same number of stars in every row
- A triangle: the inner loop depends on the row number
- A pyramid: one loop for spaces, then one for stars, inside each row
- A number is prime if no divisor exists: assume so, then look for proof otherwise
- break ends the loop, continue skips the rest of the iteration
- Two common traps: a semicolon after for, and changing the loop variable inside
- Review questions
for puts initialise, test and update on one line
Runs once, before everything else.
int i = 1Checked before every iteration, just as in while.
i <= 3Runs after the loop body in every iteration.
i++Your first for loop
Predict the output, then run. Change 3 to 6 and run again. Notice that the three parts are separated by semicolons, ;.
public class FirstFor {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
System.out.println("Hello " + i);
}
System.out.println("Done");
}
}Hello 1 Hello 2 Hello 3 Done
Semicolons, not commas
Fix the for line so the program prints 0, 1 and 2.
public class ForCommas {
public static void main(String[] args) {
for (int i = 0, i < 3, i++) {
System.out.println(i);
}
}
}';' expectedShow the fix
public class ForCommas {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
}
}0 1 2
Why? The three parts are separate statements, and semicolons are what separate them. On seeing a comma, the compiler assumed you were declaring another variable, so it could not make sense of what follows.
Every for loop is a while loop, neatly arranged
whileint i = 1;
while (i <= 3) {
System.out.println(i);
i++;
}forfor (int i = 1; i <= 3; i++) {
System.out.println(i);
}- Initialise once
- Check the testIf it is
false, the loop ends. - Run the body
- Update, then go back to the test
See the order in the debugger
Press "Debug line by line", then "Next line". Because the three parts share one line, the highlight sits on the for line more than once and returns to it after each body. Watch the box i: when does it change, before the body or after it?
public class TraceFor {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
System.out.println(i);
}
System.out.println("Done");
}
}1 2 3 Done
When does the i++ part of a for loop run?
while body. That is why i in the first iteration is the initial value itself.Counting can go up, down or in any step we want
| Goal | The line | Values |
|---|---|---|
| Up | for (int i = 1; i <= 5; i++) | 1 2 3 4 5 |
| Down | for (int i = 5; i >= 1; i--) | 5 4 3 2 1 |
| In steps of 5 | for (int i = 0; i <= 20; i += 5) | 0 5 10 15 20 |
| Odd numbers | for (int i = 1; i < 10; i += 2) | 1 3 5 7 9 |
Three loops in one program
We use print to keep the values on one line, then an empty println() to move to the next line. Change the third loop to print the multiples of 3 up to 30.
public class Countings {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 5; i >= 1; i--) {
System.out.print(i + " ");
}
System.out.println();
for (int i = 0; i <= 20; i += 5) {
System.out.print(i + " ");
}
System.out.println();
}
}1 2 3 4 5 5 4 3 2 1 0 5 10 15 20
Down in steps of 3. What does this print?
public class DownByThree {
public static void main(String[] args) {
for (int i = 10; i > 0; i -= 3) {
System.out.println(i);
}
}
}Show the output
10 7 4 1
Why? After 1, i becomes -2, so the test i > 0 is false before printing, which is why -2 never appears.
A loop variable declared in for does not outlive the loop
The scope of a variable is the part of the program where its name is known. A variable declared on the for line is known only inside the loop, which is why each loop can declare its own i, as you saw in the Countings program.
A name that no longer exists
We want to print i after the loop ends. Fix the program so it prints 1, 2 and 3, then After: 4.
public class AfterLoop {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
System.out.println(i);
}
System.out.println("After: " + i);
}
}cannot find symbolShow the fix
public class AfterLoop {
public static void main(String[] args) {
int i;
for (i = 1; i <= 3; i++) {
System.out.println(i);
}
System.out.println("After: " + i);
}
}1 2 3 After: 4
Why? After the closing brace of the loop, i no longer exists. If you need its value after the loop, declare it before the loop.
The same name twice
Fix the program so it prints 5, then 0 and 1, without changing the numbers.
public class TwoNames {
public static void main(String[] args) {
int i = 5;
System.out.println(i);
for (int i = 0; i < 2; i++) {
System.out.println(i);
}
}
}variable i is already definedShow the fix
public class TwoNames {
public static void main(String[] args) {
int total = 5;
System.out.println(total);
for (int i = 0; i < 2; i++) {
System.out.println(i);
}
}
}5 0 1
Why? The first i is still alive at the for line, so another variable with the same name cannot be declared inside its scope. Rename one of them.
for suits a known count, while suits ending on an event
| Situation | Best fit | Example |
|---|---|---|
| The count is known before starting | for | Print the 7 times table |
| The loop stops on an event | while | Read until -1, or until a number reaches 0 |
| The body must run at least once | do-while | Ask until the answer is valid |
Which loop fits adding the digits of a number the user entered?
Which loop fits reading the grades of exactly 30 students?
for keeps all the counting on one line.A sum starts at 0, a product starts at 1
Sum and product together
Trace the program and watch the boxes sum and product. Change 5 to 10 and predict which grows faster. Why did we choose long for the product?
public class SumAndProduct {
public static void main(String[] args) {
int sum = 0;
long product = 1;
for (int i = 1; i <= 5; i++) {
sum += i;
product *= i;
}
System.out.println("Sum: " + sum);
System.out.println("Product: " + product);
}
}Sum: 15 Product: 120
Sum of the even numbers
Read a number n, then print the sum of the even numbers from 2 to n. Print nothing else. If n is less than 2 the answer is 0.
import java.util.Scanner;
public class SumOfEvens {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
// Add the even numbers from 2 to n, then print the sum
}
}10
30
Hint 1
You can start at 2 and step by 2, so you do not need an if.
Hint 2
The loop line: for (int i = 2; i <= n; i += 2).
Solution
import java.util.Scanner;
public class SumOfEvens {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int sum = 0;
for (int i = 2; i <= n; i += 2) {
sum += i;
}
System.out.println(sum);
}
}A times table is one loop and one print line
Choose a number
Run the program and enter a number yourself, then change the loop to print the table downwards from 10 to 1.
import java.util.Scanner;
public class TimesTable {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Number: ");
int n = input.nextInt();
for (int i = 1; i <= 10; i++) {
System.out.println(n + " x " + i + " = " + n * i);
}
}
}Parentheses and joining text, from earlier lectures. What does this print?
public class TimesTrap {
public static void main(String[] args) {
for (int i = 1; i <= 2; i++) {
System.out.println("Result: " + 3 + i);
System.out.println("Result: " + (3 + i));
}
}
}Show the output
Result: 31 Result: 4 Result: 32 Result: 5
Why? Without parentheses "Result: " + 3 becomes text and i is stuck on. With them, 3 + i is added first. The n * i in the last program needs no parentheses, because multiplication comes before +.
The times table
Read a number n without printing a prompt, then print its times table from 1 to 10 in the form 3 x 1 = 3.
import java.util.Scanner;
public class TimesExercise {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
// Print ten lines
}
}3
3 x 1 = 3 3 x 2 = 6 3 x 3 = 9 3 x 4 = 12 3 x 5 = 15 3 x 6 = 18 3 x 7 = 21 3 x 8 = 24 3 x 9 = 27 3 x 10 = 30
Hint 1
Watch the spaces: n + " x " + i + " = " + n * i.
Solution
import java.util.Scanner;
public class TimesExercise {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
for (int i = 1; i <= 10; i++) {
System.out.println(n + " x " + i + " = " + n * i);
}
}
}In a nested loop, the inner loop finishes completely for each outer iteration
Think of a clock: the minute hand goes all the way round each time the hour hand moves one step. The outer loop is the hour hand, and the inner loop is the minute hand.
Trace i and j
Press "Debug line by line", then "Next line" many times. Before each press, predict i and j. Notice that j starts again from 1 each time i changes. Then change 3 to 2 and work out the number of lines before running.
public class NestedTrace {
public static void main(String[] args) {
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= 3; j++) {
System.out.println("i=" + i + " j=" + j);
}
System.out.println("end of i=" + i);
}
}
}i=1 j=1 i=1 j=2 i=1 j=3 end of i=1 i=2 j=1 i=2 j=2 i=2 j=3 end of i=2
i | Values of j in this iteration | j when the inner loop ends | Lines printed |
|---|---|---|---|
1 | 1 2 3 | 4 | 3 + 1 |
2 | 1 2 3 | 4 | 3 + 1 |
How many times does the line count++ run?
for (int i = 0; i < 4; i++) {
for (int k = 0; k < 5; k++) {
count++;
}
}
print stays on the line and println ends it, so together they make a grid
This is the secret of all the patterns to come: the inner loop writes one line with print, the println() after it ends that line, and the outer loop repeats the lines.
The multiplication grid
We use \t to line the columns up. Trace one row only, then press Continue. Then grow the grid to 5 rows and 5 columns, and delete the println() to see what happens.
public class MultiplicationGrid {
public static void main(String[] args) {
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= 4; col++) {
System.out.print(row * col + "\t");
}
System.out.println();
}
}
}1 2 3 4 2 4 6 8 3 6 9 12
We moved the println inside the inner loop. What does this print?
public class InnerPrintln {
public static void main(String[] args) {
for (int row = 1; row <= 2; row++) {
for (int col = 1; col <= 2; col++) {
System.out.print("*");
System.out.println();
}
}
}
}Show the output
* * * *
Why? println() runs after every star, so each star gets its own line: 2 × 2 = 4 lines. Where the println sits decides the shape of the output.
A rectangle: the same number of stars in every row
- How many rows?That is how many times the outer loop turns.
- How many stars in row number
row?That is the test of the inner loop, and it is the key question in every pattern. - End each row with
println()
A rectangle of stars
Predict the shape before running. Then change it to 2 rows and 7 columns, and after that change the star to #.
public class Rectangle {
public static void main(String[] args) {
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= 5; col++) {
System.out.print("*");
}
System.out.println();
}
}
}***** ***** *****
A triangle: the inner loop depends on the row number
The only difference from the rectangle is that the inner test is now col <= row instead of a fixed number: row 1 has one star, row 2 has two, and so on.
A right triangle
Trace the first two rows and watch how many times the inner loop turns. Then print row in place of the star, and after that print col: what is the difference?
public class Triangle {
public static void main(String[] args) {
for (int row = 1; row <= 4; row++) {
for (int col = 1; col <= row; col++) {
System.out.print("*");
}
System.out.println();
}
}
}* ** *** ****
An upside-down triangle
Read a number n, then print an upside-down triangle: n stars in the first row, one fewer in each row, down to one star. Print nothing else.
import java.util.Scanner;
public class InvertedTriangle {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
// Print the triangle using two nested for loops
}
}4
**** *** ** *
Hint 1
Make the outer loop count down: row starts at n and ends at 1.
Hint 2
The number of stars in a row still equals row.
Solution
import java.util.Scanner;
public class InvertedTriangle {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
for (int row = n; row >= 1; row--) {
for (int col = 1; col <= row; col++) {
System.out.print("*");
}
System.out.println();
}
}
}A pyramid: one loop for spaces, then one for stars, inside each row
Row row | Spaces n - row | Stars 2 * row - 1 |
|---|---|---|
1 | 3 | 1 |
2 | 2 | 3 |
3 | 1 | 5 |
4 | 0 | 7 |
The pyramid
Trace the first row only, then press Continue. Change n to 6. Then delete the spaces loop and explain the shape you get.
public class Pyramid {
public static void main(String[] args) {
int n = 4;
for (int row = 1; row <= n; row++) {
for (int s = 1; s <= n - row; s++) {
System.out.print(" ");
}
for (int star = 1; star <= 2 * row - 1; star++) {
System.out.print("*");
}
System.out.println();
}
}
}* *** ***** *******
A right-aligned triangle
Read n and print a right-aligned triangle: row number row has n - row spaces, then row stars. Print nothing else.
import java.util.Scanner;
public class RightAligned {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
// One outer loop, with two loops inside it
}
}3
* ** ***
Hint 1
Copy the shape of the pyramid and change only the number of stars.
Hint 2
The test of the stars loop is star <= row.
Solution
import java.util.Scanner;
public class RightAligned {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
for (int row = 1; row <= n; row++) {
for (int s = 1; s <= n - row; s++) {
System.out.print(" ");
}
for (int star = 1; star <= row; star++) {
System.out.print("*");
}
System.out.println();
}
}
}A number is prime if no divisor exists: assume so, then look for proof otherwise
A prime number is greater than 1 and divides only by 1 and itself. The pattern is a flag variable: a boolean we assume is true, then change to false at the first evidence.
Check the number
Trace the program and watch i and prime. Then change n to 21 and trace it again: at what value of i does prime change? Do the remaining iterations help after that? We return to this question in the next section.
public class PrimeCheck {
public static void main(String[] args) {
int n = 7;
boolean prime = n > 1;
for (int i = 2; i < n; i++) {
if (n % i == 0) {
prime = false;
}
}
System.out.println(n + " prime? " + prime);
}
}7 prime? true
The primes up to n
Read n and print the primes from 2 to n on one line, with a space after each. You will need an outer loop over the numbers and an inner loop that checks each one.
import java.util.Scanner;
public class PrimesUpTo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
// For each number from 2 to n, check it, then print it if it is prime
System.out.println();
}
}10
2 3 5 7
Hint 1
Declare boolean prime = true; inside the outer loop, so it goes back to true for each new number.
Hint 2
Pick another name for the inner loop, such as d: the divisor is not the number being checked.
Solution
import java.util.Scanner;
public class PrimesUpTo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
for (int number = 2; number <= n; number++) {
boolean prime = true;
for (int d = 2; d < number; d++) {
if (number % d == 0) {
prime = false;
}
}
if (prime) {
System.out.print(number + " ");
}
}
System.out.println();
}
}break ends the loop, continue skips the rest of the iteration
Stop at the first evidence
This answers the question from the last section: once a divisor is found, searching further is pointless. Trace the program and notice that the loop ends at i = 3 without carrying on to 20. Delete break and trace it again to compare.
public class PrimeBreak {
public static void main(String[] args) {
int n = 21;
boolean prime = n > 1;
for (int i = 2; i < n; i++) {
if (n % i == 0) {
prime = false;
System.out.println("Divisor: " + i);
break;
}
}
System.out.println(n + " prime? " + prime);
}
}Divisor: 3 21 prime? false
continue jumps straight to the update. What does this print?
public class ContinueSkip {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue;
}
System.out.print(i + " ");
}
System.out.println();
for (int i = 1; i <= 5; i++) {
if (i == 3) {
break;
}
System.out.print(i + " ");
}
System.out.println();
}
}Show the output
1 2 4 5 1 2
Why? continue skips printing 3 and carries on with the update. break ends the whole loop at 3, so nothing more prints.
int i = 1;
while (i <= 5) {
if (i == 3) {
continue;
}
System.out.println(i);
i++;
}while, continue jumps to the test, so if the update comes after it, i never changes and the loop is infinite. Type this fragment inside main in the lab above, in place of its current lines, then press Stop.Optional: a labelled break
A plain break leaves only the inner loop. To leave both loops at once, put a label before the outer one. Remove the name outer from the break line and compare the output. We rarely need this.
public class LabelledBreak {
public static void main(String[] args) {
outer:
for (int i = 1; i <= 3; i++) {
for (int k = 1; k <= 3; k++) {
if (i * k == 4) {
break outer;
}
System.out.println(i + " x " + k);
}
}
}
}1 x 1 1 x 2 1 x 3 2 x 1
Two common traps: a semicolon after for, and changing the loop variable inside
Look closely at the end of the for line. How many times does Hello print?
public class SemicolonTrap {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++);
{
System.out.println("Hello");
}
}
}Show the output
Hello
Why? The semicolon is the loop body: an empty statement repeated 3 times. The braces after it are not part of the loop, so Hello prints once, with no message from the compiler.
A message that looks unrelated
The message complains about i, yet i is declared right there. Where is the mistake?
public class SemicolonError {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++);
{
System.out.println(i);
}
}
}cannot find symbolShow the fix
public class SemicolonError {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
System.out.println(i);
}
}
}1 2 3
Why? The semicolon ended the loop, and the scope of i ended with it, leaving the print line outside the loop. So the compiler does not know i there, although the real cause is on the line before.
We also grow i inside the body. What does this print?
public class ModifyLoopVar {
public static void main(String[] args) {
for (int i = 0; i < 6; i++) {
System.out.println(i);
i++;
}
}
}Show the output
0 2 4
Why? i grows twice per iteration, once in the body and once in the update, so the odd numbers are skipped. Anyone reading only the for line would think the loop turns 6 times.
Review questions
How many times does the body of for (int i = 3; i < 15; i += 3) run?
false before the body runs.Inside two nested loops, which loop does a plain break take you out of?
break ends the nearest loop around it, and the outer loop carries on with its next iteration.Which inner test makes the shape a triangle rather than a rectangle?
Trace on paper, then check with the debugger. What does this print?
public class ReviewNested {
public static void main(String[] args) {
int total = 0;
for (int i = 1; i <= 3; i++) {
for (int k = 1; k <= i; k++) {
total += k;
}
}
System.out.println(total);
}
}Show the output
10
Why? At i = 1 we add 1, at i = 2 we add 1 + 2 and at i = 3 we add 1 + 2 + 3. The total is 1 + 3 + 6 = 10.