Control Statements and Subroutines
Control statements control the flow of a program's execution, which is the order in which its statements are carried out.
Why Programs Need Control Flow
A program is more than a list of instructions that the computer reads from top to bottom. Real programs need to decide what work to do, repeat some work, and skip other work depending on the situation. The tools that make these decisions are called control statements. Their job is to control the flow of a program's execution, meaning the order in which its statements are carried out.
The course material introduces control statements through Interest3.java from Section 3.1, which is the first example in the material that uses control statements. Before you meet the individual control statements, it helps to picture what execution looks like both with and without control. Once you can do that, the specific statements become much easier to read.
A useful picture is a single pointer that moves through the program. The pointer lands on a statement, that statement is carried out, and then the pointer moves on. Keep this pointer in mind through the rest of the article, because every control statement is simply something that can change where the pointer goes next.
Sequential Flow as the Default
When no control statement changes it, execution moves from each statement to the next one in sequence. The pointer goes to the first statement, carries it out, then moves to the statement right after it, and so on until the statements run out. This is the simplest case, and the rest of the topic is about how control statements alter that path.
7- The first statement runs first and stores 4 in a
- The second statement runs next and stores 7 in b
- The third statement runs last and prints 7
Tracing a Program One Step at a Time
To understand control flow in any program, trace its execution step by step and record the state of the variables after each step. Tracing means you act as the computer: you move the pointer, carry out one statement, write down what changed, and then decide where the pointer goes next. This habit is the main technique for reading programs with control flow, and it works the same way for every program.
- n is assigned 7 first
- The if tests n % 2 == 0, which checks whether n is even
- The else block holds the statement that runs when the test is false
- The last statement always runs after the if-else is finished
What do you think happens?
What does the program print, and in what order?
Reveal answer
It prints odd and then done. The even line is never carried out.
The test n % 2 == 0 is false because 7 % 2 is 1. Execution therefore takes the else path and prints odd. The statement that prints done is not part of the if-else, so it runs afterward.
Read the state diagram from top to bottom. The value 7 is stored first. The condition is tested with the current value, and because 7 % 2 is 1, the condition is false. The pointer then takes the false path to the statement that prints odd. The statement that prints even is never reached for this value, even though it appears in the source code. If you change the value of n, the path changes while the code itself stays the same.
What a Control Statement Changes
A control statement determines which statements run next, so the same code can take different paths depending on values at run time.
An ordinary statement, such as an assignment or a print, does its work and then lets the pointer move to the next statement in the sequence. A control statement does its work too, but it also decides where the pointer goes next. The sequence is the default, and a control statement is the thing that can override it.
| Feature | Ordinary statement | Control statement |
|---|---|---|
| What it does | Carries out its own work | Decides which statements run next |
| Where the pointer goes next | The next statement in sequence | A path chosen by the statement, based on values at run time |
| Effect on the same code | Always runs when reached | The same code can take different paths on different runs |
Ordinary and control statements differ in what they do to the order of execution.
Choosing Between Two Branches
A common pattern is a decision with two branches. The program evaluates a condition, and the result of that condition decides which branch runs. To trace a decision, evaluate its condition with the current values, and then follow only the matching branch. After the branch finishes, the two paths rejoin and the pointer continues with the statement after the decision.
The figure shows the two possible paths. For the value 7, the condition is false, so the false edge is taken and print odd runs. The print even statement is skipped. The two paths rejoin at print done, which runs for every value of n. Changing n to 8 would send the pointer down the true edge instead, and the same code would print even.
Subroutines and Reuse
A subroutine is a block of code written once and called from several places, often with different input values.
A subroutine lets a program reuse a block of code instead of writing it again at each place it is needed. When a subroutine is called, execution moves into its block. When the subroutine finishes, execution returns to the caller and continues from where the call was made. The same block can be called many times, and each call can pass in a different input value.
6
20- twice is defined once as a block of code
- main calls twice with 3, and the result 6 is stored in a
- main then calls twice with 10, reusing the same block
- The body of twice does not change between the two calls
Following a Call and Return
When main reaches the call twice(3), execution moves into the twice block with x set to 3. When twice finishes with its return statement, execution goes back to the caller and continues in main. The diagram shows the state at the moment twice is running for the first call. The block that is active is shown at the top, and the caller that is waiting to continue is shown below it.
- 1main reaches the call
twice(3)and execution moves into the twice block with x set to 3 - 2twice runs its return statement and produces 6, so the block finishes
- 3Execution returns to main, which continues with the statement after the call and stores 6
- 4main reaches the call
twice(10), which starts a new activation of the same block with x set to 10 - 5twice produces 20, the block finishes, and execution returns to main to continue
After twice returns 6, that block is finished and only main remains. The next call, twice(10), starts a new run of the same block with x set to 10. The code of twice did not change between the two calls. Only the value passed in was different.
Mistakes Learners Make with Control Flow
Common mistake Assuming every statement in the source code runs
What it looks likeReading the odd or even program and expecting both print statements to run for n = 7
Why it failsA decision sends execution down only one branch for the current values, so the other branch is skipped
Do this insteadEvaluate the condition with the current values and follow only the matching branch
Common mistake Tracing a program without recording the variable values
What it looks likeStepping through the program in your head but forgetting that n holds 7 after the first line
Why it failsA condition depends on values at run time, so you cannot decide the path without knowing the state
Do this insteadWrite down the state of the variables after each step, as the hand trace does
Common mistake Thinking a subroutine runs only once because it is written once
What it looks likeBelieving that twice has only one result because its definition appears once in the file
Why it failsA subroutine is written once but can be called from several places, each with its own input
Do this insteadFollow each call separately, noting the input value and the result returned
Common mistake Forgetting where execution resumes after a call
What it looks likeAssuming the program jumps to the statement after the subroutine definition when twice finishes
Why it failsExecution returns to the caller, and continues from the point where the call was made
Do this insteadAfter the subroutine finishes, return to the statement in the caller that made the call
Practice Tracing Flow
Trace the odd or even program with n set to 8 instead of 7. Write down the value of n, the result of the test, the branch taken, and the output after each step. Then say which line is skipped and whether the final line still runs.
Hints
- Compute 8 % 2 before deciding which branch the condition selects
- The branch that prints even is taken when the condition is true
- The line that prints done is after the if-else, so it runs for every value of n
Using the twice subroutine from this article, write out the order of execution for a program that calls twice(4) and then twice(7). For each call, state the value of x, the value returned, and the statement in main where execution resumes.
Hints
- Each call starts a new run of the same block with a new value of x
- The block finishes at its return statement, and execution goes back to the caller
Key Takeaways
- A control statement controls the flow of a program's execution, which is the order in which its statements are carried out, and decides which statements run next
- With no control statement changing it, execution moves from each statement to the next one in sequence
- To trace a program, follow the flow one step at a time, record the variable values after each step, and at a decision follow only the branch the current values select
- A subroutine is a block of code written once and called from several places, often with different inputs; execution moves into it on a call and returns to the caller when it finishes
Interest3.javafrom Section 3.1 is the first example in the material that uses control statements, andThreeN2.javais cited as an example that uses subroutines