Concepts / Control Statements

Control Statements

A control statement determines which statements run next, so the same code can take different paths depending on values at run time

  • Programming

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?

  • even

  • odd

Reveal answer
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.

QuestionSequential flowControl-directed flow
What decides the next statement?The position of the statement in the source fileThe result of a condition evaluated with current values
Can a statement be skipped?No, each statement runs in orderYes, a branch that is not chosen does not run
Does changing the values change the path?No, the path is always the sameYes, different values can take different branches

Two ways the path of execution can differ

Key point

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.

java
Output
odd
done
Notes on the code
  • 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
Worked example

Following the path when n is 7

Trace which statements run for the ParityCheck program when n is 7.

  1. 1
    Store the value

    Execution reaches int n = 7, so n holds 7 from this point on.

  2. 2
    Evaluate the condition

    The remainder 7 % 2 is 1, so n % 2 == 0 is false.

  3. 3
    Take the false edge

    Because the condition is false, execution skips the then-part and runs the else branch, which prints odd.

  4. 4
    Rejoin and finish

    After the if statement ends, the statement that prints done runs. The line that prints even is never reached in this run.

Result

The program prints odd and then done.

n = 7n % 2 == 0 ?print evenprint doneprint oddtruefalse
Which statements run next when the condition is false, and where do the two paths rejoin? For n equal to 7 the false edge is taken, so print odd runs and print even is skipped before both paths meet at print 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

Definition

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.

java
Output
6
20
Notes on the code
  • 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

  1. 1
    main reaches the statement that calls twice(3), so execution leaves main and moves into the twice block with x set to 3.
  2. 2
    twice runs its return statement, which produces the value 6, and the block finishes.
  3. 3
    Execution goes back to the caller, main, and continues from the point just after the call. The value 6 is stored in first and printed.
  4. 4
    main reaches twice(10). This starts a new run of the same block with x set to 10, and the return produces 20.
  5. 5
    After the second return, only main remains, and it continues to the end of its code.
maintwicecall twice(3), x = 3return 6call twice(10), x = 10return 20
When main calls twice, what runs first, and where does execution resume after twice finishes? Each call moves control into twice, and each return moves it back to main, which then continues.

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 like

    Believing that print even and print odd both appear when n is 7.

    Why it fails

    A control statement sends execution down only the branch that matches the condition's result. The other branch is skipped on that run.

    Do this instead

    Evaluate the condition with the current value, then follow only the matching edge.

  • Common mistake

    Tracing a branch with the wrong value

    What it looks like

    Using n = 8 when deciding which line prints for n = 7.

    Why it fails

    The condition depends on the values present at run time, so the path changes when the value changes.

    Do this instead

    Write down the value of each variable before you evaluate the condition.

  • Common mistake

    Expecting a subroutine to run only once

    What it looks like

    Thinking that twice has finished for good after the call twice(3).

    Why it fails

    A subroutine is written once but can be called many times. Each call starts a new run with its own input value.

    Do this instead

    Trace 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

EASY

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
MEDIUM

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.