Control Statements
A control statement determines which statements run next, so the same code can take different paths depending on values at run time
A Program That Takes Different Paths
Many programs are not a fixed list of statements that always run from top to bottom in one way. Some statements decide what runs next, so the same code can produce different results depending on the values it sees while it runs. Statements of this kind are called control statements. In this article you will trace how they choose a path, and then you will look at subroutines, which are blocks of code that are written once and run when the program asks for them.
What do you think happens?
In the program below, n is 7. Which line will be printed?
Reveal answer
odd
The condition n % 2 == 0 is tested with n equal to 7. The remainder 7 % 2 is 1, so the condition is false, and the else branch prints odd. The even line is never reached for this value, even though it appears in the source code.
Sequential Flow Versus Control-Directed Flow
Without control statements, a program runs its statements in order. Each statement finishes, and the next one below it starts. A control statement changes this order. It evaluates a condition, and the result of that evaluation determines which statement comes next. Some statements in a program are skipped entirely on a given run, and others are reached only because a decision sent execution toward them.
| Question | Sequential flow | Control-directed flow |
|---|---|---|
| What decides the next statement? | The position of the statement in the source file | The result of a condition evaluated with current values |
| Can a statement be skipped? | No, each statement runs in order | Yes, a branch that is not chosen does not run |
| Does changing the values change the path? | No, the path is always the same | Yes, different values can take different branches |
Two ways the path of execution can differ
To trace a decision, evaluate its condition with the current values and follow only the matching branch.
Tracing a Two-Branch Decision
A common pattern is a decision with two branches. The program evaluates a condition, and the result decides which branch runs. The example below is an original illustration written for practice, not a file from the course. It stores the value 7 in n, tests whether the remainder of n divided by 2 is 0, and prints a word that depends on the answer.
odd
done- n is stored with the value 7 before the decision is reached
- The if condition is tested with the current value of n
- The else branch is the one that runs when the condition is false
- The final print statement runs after either branch, so the two paths rejoin there
Following the path when n is 7
Trace which statements run for the ParityCheck program when n is 7.
- 1Store the value
Execution reaches int n = 7, so n holds 7 from this point on.
- 2Evaluate the condition
The remainder 7 % 2 is 1, so n % 2 == 0 is false.
- 3Take the false edge
Because the condition is false, execution skips the then-part and runs the else branch, which prints odd.
- 4Rejoin and finish
After the if statement ends, the statement that prints done runs. The line that prints even is never reached in this run.
The program prints odd and then done.
Read the diagram from the top. The value 7 is stored first. The condition is tested, and because 7 % 2 is 1, the condition is false. Execution therefore follows the false edge into print odd. The print even box is never reached on this run. Changing the value of n changes which branch is taken, but the code itself stays exactly the same.
Subroutines as Reusable Blocks
A subroutine is a block of code written once and called from several places, often with different input values. The block does its work with whatever value it receives, and the caller can then use the result it returns.
The example below is an original illustration written for practice. It defines a method named twice that takes a number x and returns 2 times x. The main method calls twice twice, once with 3 and once with 10. The body of twice is written only once, yet it produces two different results because each call passes a different input.
6
20- twice is defined once, with its body in a single place
- The call
twice(3)starts the block with x set to 3 - The return statement sends the value back to the caller
- The second call starts a new run of the same block with x set to 10
Order of Execution Through a Call and Return
- 1main reaches the statement that calls
twice(3), so execution leaves main and moves into the twice block with x set to 3. - 2twice runs its return statement, which produces the value 6, and the block finishes.
- 3Execution goes back to the caller, main, and continues from the point just after the call. The value 6 is stored in first and printed.
- 4main reaches
twice(10). This starts a new run of the same block with x set to 10, and the return produces 20. - 5After the second return, only main remains, and it continues to the end of its code.
The figure shows the order of the messages. The call with 3 is active first, and main waits for it to finish. After twice returns 6, that block is finished and only main remains active. The next call, twice(10), starts a new activation of the same block. The code of twice did not change between the two calls. Only the value passed in was different, and that is what makes a subroutine reusable.
Mistakes Beginners Make with Branches and Calls
Common mistake Assuming both branches run
What it looks likeBelieving that print even and print odd both appear when n is 7.
Why it failsA control statement sends execution down only the branch that matches the condition's result. The other branch is skipped on that run.
Do this insteadEvaluate the condition with the current value, then follow only the matching edge.
Common mistake Tracing a branch with the wrong value
What it looks likeUsing n = 8 when deciding which line prints for n = 7.
Why it failsThe condition depends on the values present at run time, so the path changes when the value changes.
Do this insteadWrite down the value of each variable before you evaluate the condition.
Common mistake Expecting a subroutine to run only once
What it looks likeThinking that twice has finished for good after the call twice(3).
Why it failsA subroutine is written once but can be called many times. Each call starts a new run with its own input value.
Do this insteadTrace each call separately and note the input value each one receives.
Common mistake Forgetting where execution resumes after a call finishes, so the next statement in the caller is skipped in the trace
Practice Tracing Control Flow
Using the ParityCheck program, change the value of n to 10 and predict the output. Then trace the path: which condition result is produced, which branch runs, and what line prints last?
Hints
- Compute 10 % 2 first and check whether the result is 0
- If the condition is true, the then-branch runs, and the else-branch is skipped
- The final print of done runs whichever branch was taken
Predict the output of TwiceDemo if the second call is changed to twice(0) and then check your answer by tracing the call and return order step by step.
Hints
- Multiply 2 by the input value in each call
- Each call runs the body of twice once, with its own value of x
Key Takeaways
- A control statement determines which statements run next, so the same code can take different paths depending on values present at run time.
- To trace a decision, evaluate its condition with the current values and follow only the matching branch, then continue where the branches rejoin.
- A subroutine is a block of code written once and called from several places, often with different input values.
- When a subroutine is called, execution moves into its block, and when the subroutine finishes, execution returns to the caller and continues there.