Cambridge AS & A Level · Part 2 · Chapter 14
Programming and Data Representation
Turning pseudocode into real programs. Every construct from the chapter is shown side by side in pseudocode and Python, with VB.NET and Java noted where they differ. Every task, question and exam question is here too, with labs to try each idea.
Guru Jazzy🎯 Learning objectives
By the end of this chapter you should be able to:
- write a program in a high-level language (Python, Visual Basic console mode, Java)
- implement and write pseudocode from a design given as a program flowchart or structured English
- write pseudocode and program statements for declaring variables and constants, assigning values, expressions with arithmetic or logical operators, and keyboard input and console output
- use built-in functions and library routines, including string/character manipulation and the random number generator
- use an IF structure, including the ELSE clause and nested IFs
- Use a CASE structure
- use a loop: count-controlled, post-condition and pre-condition
- justify why one loop structure suits a problem better than the others
- define and use a procedure, and say where in an algorithm one is appropriate
- use parameters, and understand passing them by reference and by value
- define and use a function; a function is used in an expression, and its return value replaces the call
- use the terms procedure/function header, interface, parameter, argument and return value
- Write efficient code
🗣️ 14.01 Programming languages
Chapters 12 and 13 described solutions as flowcharts and pseudocode, built from the basic constructs: assignment, sequence, selection, iteration, input and output. To turn a solution into a program, you need the syntax (the correct structure of statements) for those constructs in a real language. The book gives the syntax for Python, Visual Basic console mode (VB.NET) and Java. The definitive pseudocode syntax is repeated at each point.
You only need to learn one of the three languages. Programming is only examined at A Level, but starting at AS Level means you'll be well prepared. In the AS exams, write pseudocode, not program code.
- Conceived by Guido van Rossum in the late 1980s (2.0 in 2000, 3.0 in 2008).
- Multi-paradigm: object-oriented and structured.
- Every statement on a separate line.
- Indentation is significant (the "off-side rule").
- Keywords are lower case.
- Case sensitive:
Number1,number1andNUMBER1are three different identifiers. - Everything is an object; heavy use of slicing.
- Programs are interpreted.
- Multi-paradigm, high-level, on the .NET Framework (2002). IDE: Visual Studio.
- One statement per line (a colon can join them, but don't).
- Indentation is good practice.
- Not case sensitive; the editor copies the case of the first definition.
- Convention: CamelCaps (PascalCaps).
- Programs are compiled. End with
Console.ReadLine()to keep the console window open.
- James Gosling, Sun Microsystems, 1995. JRE for users, JDK for developers.
- Every statement ends with a semicolon
;. - Case sensitive; camelCaps for identifiers, capitalised class names.
- A compound statement is a sequence inside braces
{ }. - Compiled into bytecode, run on the Java Virtual Machine.
- Almost entirely object-oriented: all code lives inside classes.
Running your first program
In Python you can type a statement straight into the Python Shell and the interpreter runs it immediately (Figure 14.01). You can also type a program into an editor such as IDLE, save it with a .py extension and run it from the Run menu (Figure 14.02).
The same "Hello World!" in VB.NET and Java (Figures 14.03 and 14.04)
In VB.NET and Java you type the code into an IDE, save it and click Run. That starts the compiler; if there are no syntax errors the program runs and its output appears in a console or Output window. A Java source file must be named after the public class it contains (for example Ex1.java), which compiles to Ex1.class. main is not a keyword, just the method the Java launcher calls first.
🧱 14.02 Programming basics
Declaration of variables
Most languages make you declare the type of data a variable will hold, so the compiler can reserve the right amount of memory. A variable declared for whole numbers can't then hold strings, or the other way round. VB.NET and Java insist on declarations before use. Python is different: it tags values, so it has no variable declarations at all.
DECLARE Number1 : INTEGER // a whole number DECLARE YourName : STRING // a sequence of characters DECLARE N1, N2, N3 : INTEGER // 3 integer variables DECLARE Name1, Name2 : STRING // 2 string variables
# Number1 of type Integer # YourName of type String # N1, N2, N3 of type integer # Name1, Name2 of type string # (Python has no declarations: comment them instead)
VB.NET: Dim Number1 As Integer. Java: int number1;. Both let you group several variables of the same type on one line.
Declaration and assignment of constants
Some values never change, such as π. Rather than typing the value into statements, give it a name and declare it at the start of the program. This is good practice and makes the code easier to read.
CONSTANT Pi = 3.14
PI = 3.14 # UPPERCASE says "treat me as a constant"
# Python will still let you change it - don't!VB.NET: Const Pi = 3.14. Java: static final double PI = 3.14;. In both, the value then cannot be altered in the program.
Assignment of variables
A ← 34 B ← B + 1
A = 34 B = B + 1 # or the short form: B += 1
All three languages use = as the assignment operator. VB.NET (Dim Number1 As Integer = 0) and Java (int number1 = 0;) can initialise a variable in its declaration. VB.NET and Python allow B += 1; Java also allows b++;.
Arithmetic operators Table 14.01
| Operation | Pseudocode | Python | VB.NET | Java |
|---|---|---|---|---|
| Addition | + | + | + | + |
| Subtraction | - | - | - | - |
| Multiplication | * | * | * | * |
| Division | / | / | / | / (float or double types) |
| Exponent | ^ | ** | ^ | No operator: Math.pow(n, e) |
| Integer division | DIV | // | \ | / (integer types) |
| Modulus | MOD | % | Mod | % |
7 DIV 2 gives 3.7 MOD 2 gives 1.When an expression has more than one operator, the order of evaluation follows the rules of precedence: parentheses, exponentiation, multiplication and division, addition and subtraction.
4 * 3 – 3 ^ 2(4 * 3 – 3) ^ 24 * (3 – 3) ^ 24 * (3 – 3 ^ 2)Worked answers
4 * 3 – 3 ^ 2= 12 – 9 = 3 (power first, then ×, then –)(4 * 3 – 3) ^ 2= 9 ^ 2 = 814 * (3 – 3) ^ 2= 4 × 0 ^ 2 = 4 × 0 = 04 * (3 – 3 ^ 2)= 4 × (3 – 9) = 4 × –6 = –24
🔬 Lab: precedence, DIV and MOD drill
A fresh expression every time. Work it out in your head, then type the value.
Outputting information to the screen
An output statement can list a mixture of strings and variable values. The example print list has four items: "Hello " and ". Your number is " are strings; YourName and Number1 are variables whose values are printed.
OUTPUT "Hello ", YourName, ". Your number is ", Number1 // newline OUTPUT "Hello " // no new line
print("Hello ", YourName,
". Your number is ", Number1)
print("Hello ", end='')
# placeholder method
print("Hello {0}. Your number is {1}".format(YourName, Number1))- Python: items separated by commas;
end=''stops the move to the next line. - VB.NET: items joined with
&;Console.WriteLinemoves to the next line,Console.Writedoesn't. - Java: items joined with
+;System.out.printlnvsSystem.out.print.
A long output statement can spread over several lines, but only by breaking between print-list items, never in the middle of a string (unless you split it into two strings). Python and VB.NET also have the placeholder method: {0}, {1}… in the string stand for the variables listed after it, in order.
Getting input from the user
Always prompt the user. In INPUT "Enter a number: " A, the space between the colon and the closing quote matters: it leaves a gap before the user types.
INPUT "Enter a number: " A
A = input("Enter a number: ") # input is ALWAYS a string
A = int(A) # convert it to use it as a numberIn Python, all input is a string; convert it before doing arithmetic (Section 14.07). In VB.NET and Java the prompt must be a separate output statement; Java first needs import java.util.Scanner; and a Scanner object.
Comments
It is good practice to add comments that explain code where necessary.
// this is a comment
# this is a comment # this is another comment
VB.NET comments start with '. Java uses // for one line and /* … */ for several.
YourName first), save it as Example1 and run it. Is the output what you expected?
INPUT "What is your name? " YourName OUTPUT "Have a nice day ", YourName
Model solution
DECLARE YourName : STRING INPUT "What is your name? " YourName OUTPUT "Have a nice day ", YourName
YourName = input("What is your name? ")
print("Have a nice day ", YourName)Python's comma puts an extra space after "day", so the output is Have a nice day Sam with two spaces. That's the kind of surprise this task wants you to notice. Remove the trailing space from the string, or use "Have a nice day " + YourName.
🏷️ 14.03 Data types Tables 14.02–14.03
Every language has built-in data types. The number of bytes reserved for each type is in brackets for VB.NET and Java.
| Description of data | Pseudocode | Python | VB.NET | Java |
|---|---|---|---|---|
| Whole signed numbers | INTEGER | int | Integer (4 bytes) | int (4 bytes) |
| Signed numbers with a decimal point | REAL | float | Single (4), Double (8) | float (4), double (8) |
| A single character | CHAR, in single quotes ' | Not available: a string of length 1 | Char (2 bytes, Unicode) | char (2 bytes, Unicode) |
| A sequence of characters (a string) | STRING, in double quotes " | str; single, double or triple quotes | String (2 bytes per character) | String (2 bytes per character) |
| Logical values: True (1) and False (0) | BOOLEAN | bool: True, False | Boolean (2 bytes) | boolean: true, false |
| Date value | DATE | use the datetime class | Date (8 bytes) | a class: import java.util.Date; |
Table 14.02 Simple data types · Table 14.03 The Date data types
- In VB.NET each character takes two bytes and is stored as Unicode, where values 1–127 match ASCII.
- Python and Java have no built-in date type; a class provides it. VB.NET stores dates from 1.1.0001 to 31.12.9999 to a resolution of 100 nanoseconds (a "tick").
- Dates have various internal representations but are output in a conventional format.
- Programmers can also design their own data types (Chapter 16 and Chapter 26).
str is Unicode.🎮 Pick the data type
Which pseudocode type would you declare for this value?
- Look at the identifier tables in Chapter 12 (Tables 12.02 and 12.04–12.12). Decide which data type from your language suits each variable.
- Write program code for the pseudocode in Worked Example 12.01 in Chapter 12.
These build on Chapter 12. The rule of thumb: counts and positions → int; money and measurements → float; names and codes → str; flags such as "found" → bool.
⚖️ 14.04 Boolean expressions Tables 14.04–14.05
Chapter 12 (Section 12.06) used logic statements containing a condition. Conditions are also called Boolean expressions: they evaluate to True or False (the Boolean values). Simple ones use comparison operators; complex ones add Boolean operators.
| Operation | Pseudo | Python | VB | Java |
|---|---|---|---|---|
| equal | = | == | = | == |
| not equal | <> | != | <> | != |
| greater than | > | > | > | > |
| less than | < | < | < | < |
| greater or equal | >= | >= | >= | >= |
| less or equal | <= | <= | <= | <= |
| Operation | Pseudo | Python | VB | Java |
|---|---|---|---|---|
| AND (conjunction) | AND | and | And | && |
| OR (inclusion) | OR | or | Or | || |
| NOT (negation) | NOT | not | Not | ! |
= to compare, but Python and Java need ==. In Python, = inside an if is a syntax error.Table 14.04 Comparison operators · Table 14.05 Boolean operators
🔬 Lab: Boolean expression playground
Set the variables and watch every expression update.
| Pseudocode | Python | Value |
|---|
🔀 14.05 Selection
IF…THEN statements
IF <Boolean expression>
THEN
<statement(s)>
ENDIFPython replaces THEN with a colon : and uses indentation to show which statements are inside the condition. VB.NET puts Then on the same line as the condition and ends with End If. Java puts the condition in brackets and needs braces { } for more than one statement.
IF x < 0
THEN
OUTPUT "Negative"
ENDIFif x < 0:
print("Negative")IF…THEN…ELSE statements
IF x < 0
THEN
OUTPUT "Negative"
ELSE
OUTPUT "Positive"
ENDIFif x < 0:
print("Negative")
else:
print("Positive")The else must line up with its if. In VB.NET, Else sits on its own line, aligned with If, with the statements indented.
Nested IF statements
IF x < 0
THEN
OUTPUT "Negative"
ELSE
IF x = 0
THEN
OUTPUT "Zero"
ELSE
OUTPUT "Positive"
ENDIF
ENDIFif x < 0:
print("Negative")
elif x == 0: # elif = "else if"
print("Zero")
else:
print("Positive")elif is short for "else if" and must line up with the matching if; you can have as many elif parts as you need. VB.NET's one-word ElseIf needs only one End If. Java writes else if.
CASE statements
An alternative selection construct. Each CASE condition can be a single value, single values separated by commas, or a range. The value of <expression> decides which statements run. You can have as many cases as you need. OTHERWISE is optional and useful for error trapping.
CASE OF <expression> <value1> : <statement(s)> <value2>,<value3> : <statement(s)> <value4> TO <value5> : <statement(s)> . . OTHERWISE <statement(s)> ENDCASE
CASE OF Grade "A" : OUTPUT "Top grade" "F", "U" : OUTPUT "Fail" "B".."E" : OUTPUT "Pass" OTHERWISE OUTPUT "Invalid grade" ENDCASE
# Python has no CASE: use if/elif instead
if Grade == "A":
print("Top grade")
elif Grade == "F" or Grade == "U":
print("Fail")
elif Grade in ("B", "C", "D", "E"):
print("Pass")
else:
print("Invalid grade")Python has no CASE statement, so use nested IFs (elif). VB.NET has Select Case … Case "B" To "E" … Case Else … End Select. Java has switch, where every case needs a break; and default: plays the role of OTHERWISE.
🔬 Lab: which branch fires?
Type a grade. The highlighted line is the one that runs.
INPUT MonthNumber
INPUT Year
Days ← 0
CASE OF MonthNumber
1,3,5,7,8,10,12 : Days ← 31
4,6,9,11 : Days ← 30
2 : Days ← 28
IF Year MOD 400 = 0
THEN // it is a leap year
Days ← 29
ENDIF
IF (Year MOD 4 = 0) AND (Year MOD 100 > 0)
THEN // it is a leap year
Days ← 29
ENDIF
OTHERWISE OUTPUT "Invalid month number"
ENDCASE
OUTPUT DaysModel solution in Python
MonthNumber = int(input("Month number: "))
Year = int(input("Year: "))
Days = 0
if MonthNumber in (1, 3, 5, 7, 8, 10, 12):
Days = 31
elif MonthNumber in (4, 6, 9, 11):
Days = 30
elif MonthNumber == 2:
Days = 28
if Year % 400 == 0: # it is a leap year
Days = 29
if Year % 4 == 0 and Year % 100 > 0: # it is a leap year
Days = 29
else:
print("Invalid month number")
print(Days)The pseudocode here uses the 9618 CASE layout. The book writes each line as CASE 1,3,5… and has a lower-case If. The leap-year rule: a year divisible by 400, or divisible by 4 but not by 100.
▶ Run it
🔁 14.06 Iteration
Count-controlled (FOR) loops
FOR <control variable> ← s TO e STEP i // STEP is optional <statement(s)> NEXT <control variable>
The control variable starts at s, goes up by i each time round the loop, and the loop finishes when the control variable reaches e.
FOR x ← 1 TO 5 OUTPUT x NEXT x FOR x ← 2 TO 14 STEP 3 OUTPUT x NEXT x FOR x ← 5 TO 1 STEP -1 OUTPUT x NEXT x
for x in range(5): # 0 1 2 3 4
print(x, end=' ')
for x in range(2, 14, 3): # 2 5 8 11
print(x, end=' ')
for x in range(5, 1, -1): # 5 4 3 2
print(x, end=' ')
for x in ["a", "b", "c"]: # abc
print(x, end='')e. s and i can be left out and default to 0 and 1, and all three must be integers. That is why the book's Python output 2 5 8 11 has no 14, while the VB.NET and Java versions print 2 5 8 11 14. A Python for can also step through each element of a group, such as a list. VB.NET For x = 1 To 2.5 Step 0.5 can use reals.🔬 Lab: FOR vs range()
Choose start, end and step. Compare what the pseudocode FOR loop produces with what Python's range() produces.
Post-condition loops
A post-condition loop runs its statements at least once. The condition is checked at the end. While it is False the statements run again; when it is True, execution moves on to the next statement after the loop. Something inside the loop must eventually make the condition True, or the loop runs forever.
REPEAT <statement(s)> UNTIL <condition>
REPEAT INPUT "Enter Y or N: " Answer UNTIL Answer = "Y"
# Python has no post-condition loop.
# The book's advice: use a pre-condition loop instead.
# A common work-around that still runs the body at least once:
while True:
Answer = input("Enter Y or N: ")
if Answer == "Y":
breakVB.NET: Do … Loop Until Answer = "Y". Java: do { … } while (!(answer.equals("Y")));. Note that Java's loop repeats while its condition is true, so the condition is negated.
Pre-condition loops
The condition is checked before the statements run. They keep running while the condition is True; when it becomes False, execution moves on to the next statement after the loop. Any variable in the condition must already have a value when the loop is first reached, and something inside the loop must eventually change the condition.
WHILE <condition> DO <statement(s)> ENDWHILE
Answer ← "" WHILE Answer <> "Y" DO INPUT "Enter Y or N: " Answer ENDWHILE
Answer = ''
while Answer != 'Y':
Answer = input("Enter Y or N: ")The loop body must be indented by a fixed number of spaces, and the first statement after the loop indented less. VB.NET has Do While … Loop and also a pre-condition Do Until … Loop, which runs while its condition is False and may not run at all. Java: while (…) { … }.
Which loop structure to use?
🎮 Choose the loop
Which loop suits this job best?
🧰 14.07 Built-in functions
Programming environments provide many built-in functions. Some are always available; others have to be imported from specialist module libraries.
String manipulation functions Table 14.06
| Description | Pseudocode | Python |
|---|---|---|
Access a single character at position P in ThisString | ThisString[P] (counts from 1) | ThisString[P] (counts from 0) |
| The character whose ASCII value is i | CHR(i : INTEGER) RETURNS CHAR | chr(i) |
| The ASCII value of character ch | ASC(ch) RETURNS INTEGER | ord(ch) |
| The length of string S | LENGTH(S : STRING) RETURNS INTEGER | len(S) |
| Leftmost L characters of S | LEFT(S : STRING, L : INTEGER) RETURNS STRING | S[0:L] |
| Rightmost L characters of S | RIGHT(S : STRING, L : INTEGER) RETURNS STRING | S[-L:] |
| String of length L starting at position P in S | MID(S : STRING, P : INTEGER, L : INTEGER) RETURNS STRING | S[P : P + L] |
| Lower case equivalent of character Ch | LCASE(Ch : CHAR) RETURNS CHAR | Ch.lower() |
| Upper case equivalent of character Ch | UCASE(Ch : CHAR) RETURNS CHAR | Ch.upper() |
| S with all letters converted to upper case | TO_UPPER(S : STRING) RETURNS STRING | S.upper() |
| S with all letters converted to lower case | TO_LOWER(S : STRING) RETURNS STRING | S.lower() |
| Concatenate (join) two strings | S1 & S2 | s = S1 + S2 |
Table 14.06 Some useful string manipulation functions. VB.NET: Chr, Asc, len, Left, Right, mid, LCase, UCase, &. Java: charAt, substring, length(), toUpperCase(), +.
🎮 Predict the string function
Pseudocode counts string positions from 1. Type exactly what the call returns (no quotes).
Slicing in Python Figure 14.05
Python makes a subsequence of any sequence type (lists, strings) with a slice. A substring of length L from position P in S is S[P : P + L]. In ThisString = "ABCDEFG", ThisString[3 : 6] gives 'DEF': positions count from 0, and the upper bound is not included.
Imagine each index number sitting at the left-hand edge of its box. Then it is easy to see why the left element (lower bound) is included but the right one (upper bound) is excluded.
🔬 Lab: slice explorer
Leave a bound blank to mean "from the start" or "to the end". Negative numbers count from the end.
| Expression | Result | Explanation |
|---|---|---|
| ThisString[2:] | CDEFG | No upper bound: the slice runs to the end of the string. |
| ThisString[:2] | AB | No lower bound: the slice starts at the beginning. |
| ThisString[-2:] | FG | A negative lower bound starts the slice counting from the end. |
| ThisString[:-2] | ABCDE | A negative upper bound ends the slice that far from the end. |
Table 14.07 Some useful slices in Python. (The book's text calls the diagram "Figure 13.05"; it is Figure 14.05.)
Truncating numbers and converting strings
Sometimes you want just the whole-number part of a real number, without rounding. This is truncation. A number held as a string must be converted before it can be used in a calculation.
INT(x : REAL) RETURNS INTEGER // 7.9 → 7 STRING_TO_NUM(x : STRING) RETURNS REAL // "75.43" → 75.43
int(x) # 7.9 → 7 (truncates towards zero)
int("5") # "5" → 5
float(x) # "75.43" → 75.43VB.NET: Math.Truncate(x), CInt(S), CDbl(x). Java: (int) x;, Integer.valueOf(S), Float.valueOf(x).
Random number generator
Simulations often need random numbers. Because a program generates them, they are called pseudo-random.
import random random.randint(1, 6) # 1 to 6 inclusive
VB.NET: Dim RandomNumber As New Random then RandomNumber.Next(1, 6) gives 1 to 6 exclusive (that is, 1–5). Java: new Random().nextInt(6) + 1 gives 1–6. Both need a Random object (Chapter 27).
- Write program code to generate 20 random numbers in the range 1 to 10 inclusive.
- Write program code for the pseudocode from Worked Example 12.07 in Chapter 12, using a pre-condition loop.
Model solution to part 1
import random
for i in range(20):
print(random.randint(1, 10))🧩 14.08 Procedures
Chapter 12 (Section 12.09) used procedures to give a group of statements a name. In a program, you define the procedure before the main program, then call it from the main program whenever you want the procedure body to run.
PROCEDURE <procedureIdentifier> // this is the procedure header <statement(s)> // these statements are the procedure body ENDPROCEDURE CALL <procedureIdentifier>
PROCEDURE InputOddNumber
REPEAT
INPUT "Enter an odd number: " Number
UNTIL Number MOD 2 = 1
OUTPUT "Valid number entered"
ENDPROCEDURE
CALL InputOddNumberdef InputOddNumber():
Number = 0
while Number % 2 == 0:
Number = int(input("Enter an odd number: "))
print("Valid number entered")
#************ main program starts here ************
InputOddNumber()Python: def <identifier>():. VB.NET: Sub … End Sub. Java: void <identifier>() { … }. Notice where the definition is written and how the main program calls it.
The Python editor colour-codes the parts of each statement, which helps while typing. Indentation shows which statements belong to the loop. The built-in input returns a string, which must be converted to an integer before it can be used as a number.
VB.NET and Java versions (Figures 14.07 and 14.08)
The VB editor auto-indents, capitalises keywords, follows the capitalisation of the declaration, and is predictive. Console.ReadLine() at the end of Main keeps the run-time window open. NetBeans colour-codes keywords and strings, encloses the body in braces and shows pop-up lists as you type. Variables must be declared before use.
🧮 14.09 Functions
Section 14.07 used built-in functions: useful subroutines written by other programmers, kept in module libraries. You can write your own too, and reuse them in other programs by building up your own module library.
A function is used as part of an expression. When execution reaches a statement containing a function call, the function runs, and its return value is then used in the expression. Always return a value. You can have more than one RETURN if there are different paths through the function body.
FUNCTION <functionIdentifier> RETURNS <dataType> // function header <statement(s)> // function body RETURN <value> ENDFUNCTION
Python: def … return <value>. VB.NET: Function … As <dataType>, returning by assigning to the function name or with Return. Java: <data type> <identifier>() { … return <value>; }. A function is defined in the same place as a procedure, but called from within an expression.
| Language | PROCEDURE | FUNCTION |
|---|---|---|
| Pseudocode | PROCEDURE | FUNCTION |
| Python | void function | fruitful function |
| VB | Subroutine | Function |
| Java | void method | method |
Table 14.08 Programming language terminology for subroutines
"Void" means "nothing": Python and Java use it for a procedure-type subroutine that returns no value. Python calls both kinds functions; a fruitful function returns one or more values. Here is the procedure from Section 14.08 rewritten as a function:
FUNCTION InputOddNumber RETURNS INTEGER
REPEAT
INPUT "Enter an odd number: " Number
UNTIL Number MOD 2 = 1
OUTPUT "Valid number entered"
RETURN Number
ENDFUNCTIONdef InputOddNumber():
Number = 0
while Number % 2 == 0:
Number = int(input("Enter an odd number: "))
return Number
#********* main program starts here *********
NewNumber = InputOddNumber()The variable Number in Figure 14.09 can't be accessed in the main program: Python's variables are local unless declared global.
VB.NET and Java versions (Figures 14.10 and 14.11)
In Figure 14.10(a), Number is a global variable declared at the start of the module, which is not good practice. In 14.10(b) it is declared as a local variable inside the function. In Figure 14.11, Java's number is not accessible in the main program.
global declaration. In VB.NET you write the declaration inside the subroutine. Java has no global variables, but static variables declared in a class are accessible throughout the class.📨 14.10 Passing parameters to subroutines
When a subroutine needs values from the main program, we supply them as arguments at call time. That is how we use built-in functions, without needing to know the identifiers used inside them.
When you define a subroutine that needs values, you put a parameter list in its header. When it is called, you supply the arguments in brackets, and each one is assigned to the matching parameter. The order of parameters in the list must match the order of the arguments. This is the subroutine interface.
Argument: the actual input expression or value with which the subroutine is being called.
Parameter: the variable(s) used inside a subroutine which will take values passed into a subroutine at call time.
Subroutine interface: the parameters being passed between the subroutine and the calling program.
Function / Procedure header: the first line of a function or procedure definition, showing the identifier and parameter list.
➕ 14.11 Passing parameters to functions
FUNCTION <functionIdentifier> (<parameterList>) RETURNS <dataType>
<parameterList> is a list of identifiers and their data types, separated by commas.
FUNCTION SumRange(FirstValue : INTEGER, LastValue : INTEGER) RETURNS INTEGER
DECLARE Sum, ThisValue : INTEGER
Sum ← 0
FOR ThisValue ← FirstValue TO LastValue
Sum ← Sum + ThisValue
NEXT ThisValue
RETURN Sum
ENDFUNCTIONdef SumRange(FirstValue, LastValue):
Sum = 0
for ThisValue in range(FirstValue, LastValue + 1):
Sum = Sum + ThisValue
return Sum
#********* main program starts here *********
NewNumber = SumRange(1, 5)
print(NewNumber) # 15VB.NET and Java versions (Figures 14.13 and 14.14)
🔬 Lab: call SumRange
Supply the arguments. They are assigned to the parameters FirstValue and LastValue, in that order.
NewNumber ← SumRange(,)FUNCTION Factorial (Number : INTEGER) RETURNS INTEGER
DECLARE Product : INTEGER
Product ← 1
FOR n ← 2 TO Number
Product ← Product * n
NEXT n
RETURN Product
ENDFUNCTIONModel solution
def Factorial(Number):
Product = 1
for n in range(2, Number + 1):
Product = Product * n
return Product
print(Factorial(5)) # 120
print(Factorial(1)) # 1 (the loop never runs)🔐 14.12 Passing parameters to procedures
If a parameter is passed by value, the argument at call time can be an actual value (as in Section 14.11). If the argument is a variable, a copy of its current value is passed into the subroutine. Whatever happens in the subroutine, the variable in the calling program is unchanged.
For procedures, a parameter can also be passed by reference. The argument must then be a variable. A pointer to its memory location (its address) is passed in, so any change to the parameter changes the variable in the calling program as well.
By value: the actual value is passed into the procedure.
By reference: the address of the variable is passed into the procedure.
Neither method applies exactly to Python or Java. They use pass by object reference, an object-oriented idea covered in Chapter 27. What matters here is knowing how to get the effect you want in your language.
PROCEDURE <ProcedureIdentifier> (<parameterList>) BYREF <identifier1> : <dataType> BYVALUE <identifier2> : <dataType>
Passing parameters by value
The pyramid example from Chapter 12 (Section 12.09) has a procedure with two parameters passed by value. Now we can make that explicit:
PROCEDURE OutputSymbols(BYVALUE NumberOfSymbols : INTEGER, Symbol : CHAR)
DECLARE Count : INTEGER
FOR Count ← 1 TO NumberOfSymbols
OUTPUT Symbol // without moving to next line
NEXT Count
OUTPUT NewLine
ENDPROCEDUREdef OutputSymbols(NumberOfSymbols, Symbol):
for Count in range(NumberOfSymbols):
print(Symbol, end='')
print()
#********* main program starts here *********
OutputSymbols(5, '*') # *****In Python (Figure 14.15) and Java (Figure 14.17), all parameters behave like local variables, so the effect is as if they were passed by value. In VB.NET (Figure 14.16), parameters are passed by value by default, and the editor inserts ByVal automatically.
VB.NET and Java versions (Figures 14.16 and 14.17)
Passing parameters by reference
When parameters are passed by reference, changing their values inside the subroutine changes the variables in the calling program. The pyramid example also has a procedure with two parameters passed by reference:
PROCEDURE AdjustValuesForNextRow(BYREF Spaces : INTEGER, Symbols : INTEGER) Spaces ← Spaces - 1 Symbols ← Symbols + 2 ENDPROCEDURE CALL AdjustValuesForNextRow(NumberOfSpaces, NumberOfSymbols)
Inside the procedure, Spaces and Symbols change. After the call, NumberOfSpaces and NumberOfSymbols hold the updated values passed back from the procedure. (In 9618 pseudocode, BYREF applies to every parameter after it in the list.)
🔬 Lab: by value vs by reference, step by step
The main program holds NumberOfSpaces = 4 and NumberOfSymbols = 1, then calls AdjustValuesForNextRow. Choose how the parameters are passed and step through.
Main program
AdjustValuesForNextRow
Python cannot pass parameters by reference. Instead, the subroutine behaves as a function and returns several values (Figure 14.18). Note the order of the variables as they receive those values in the main program.
def AdjustValuesForNextRow(Spaces, Symbols):
Spaces = Spaces - 1
Symbols = Symbols + 2
return Spaces, Symbols # return BOTH values (a tuple)
#********* main program starts here *********
NumberOfSpaces = int(input())
NumberOfSymbols = int(input())
NumberOfSpaces, NumberOfSymbols = AdjustValuesForNextRow(NumberOfSpaces, NumberOfSymbols)
print(NumberOfSpaces)
print(NumberOfSymbols)Treating several values as one unit like this is called a tuple (Chapter 11, Section 11.02). In VB.NET (Figure 14.19), put ByRef in front of each parameter passed by reference. Java can't pass simple variables by reference; only objects (including arrays) are passed by reference.
VB.NET and Java versions (Figures 14.19–14.21)
🔺 14.13 Putting it all together
These programs are full solutions to the pyramid-drawing program. The subroutine parameters deliberately have different identifiers from the variables in the main program, to make it clear that parameters and local variables are separate from those in the calling program. When a parameter is passed by reference, the parameter's identifier refers to the same memory location as the variable passed as the argument.
SPACE = ' ' # constant to give a space a name
def InputMaxNumberOfSymbols():
Number = 0
while Number % 2 == 0:
print("How many symbols make the base? ")
Number = int(input("Input an odd number: "))
return Number
def SetValues():
Symbol = input("What symbol do you want to use? ")
MaxSymbols = InputMaxNumberOfSymbols()
Spaces = (MaxSymbols + 1) // 2
Symbols = 1
return Symbol, MaxSymbols, Spaces, Symbols
def OutputChars(Number, Symbol):
for Count in range(Number):
print(Symbol, end='')
def AdjustValuesForNextRow(Spaces, Symbols):
Spaces = Spaces - 1
Symbols = Symbols + 2
return Spaces, Symbols
def main():
ThisSymbol, MaxNumberOfSymbols, NumberOfSpaces, NumberOfSymbols = SetValues()
while NumberOfSymbols <= MaxNumberOfSymbols:
OutputChars(NumberOfSpaces, SPACE)
OutputChars(NumberOfSymbols, ThisSymbol)
print() # move to new line
NumberOfSpaces, NumberOfSymbols = AdjustValuesForNextRow(NumberOfSpaces, NumberOfSymbols)
main()The book also prints the full VB.NET version (with ByRef parameters and a Do … Loop Until) and a Java version that uses two functions, adjustSpacesForNextRow and adjustSymbolsForNextRow.
▶ Run the pyramid program
| Row | NumberOfSpaces | NumberOfSymbols |
|---|
OutputSpaces and OutputSymbols have been replaced by a single procedure, OutputChars, without changing what the program does?
Answer
Both procedures did the same job, printing one character a given number of times. Only the character differed. Making the character a parameter lets one procedure do both: OutputChars(NumberOfSpaces, SPACE) and OutputChars(NumberOfSymbols, ThisSymbol). Less code means fewer places for bugs.
🗃️ 14.14 Arrays
Creating and accessing 1D arrays
VB.NET, Python and Java number array elements from 0 (the lower bound). In pseudocode you choose the bounds.
DECLARE <arrayIdentifier> : ARRAY[<lowerBound>:<upperBound>] OF <dataType> DECLARE List1 : ARRAY[1:3] OF STRING // 3 elements in this list DECLARE List2 : ARRAY[0:5] OF INTEGER // 6 elements in this list DECLARE List3 : ARRAY[1:100] OF INTEGER // 100 elements in this list DECLARE List4 : ARRAY[0:25] OF STRING // 26 elements in this list NList[25] ← 0 // set 25th element to zero AList[3] ← "D" // set 3rd element to letter D
List1 = [] # no declarations: initialise instead
List1.append("Fred")
List1.append("Jack")
List1.append("Ali")
List2 = [0, 0, 0, 0, 0, 0] # enclose the elements in [ ]
List3 = [0 for i in range(100)] # use a loop
AList = [""] * 26 # initial value × number of elements
NList[24] = 0 # Python counts from 0, so [24] is the 25th element
AList[3] = "D"
print(List1) # Python can print a whole list at once- Python has no arrays. The equivalent structure is a list: an ordered sequence of items that don't have to be the same data type.
- VB.NET:
Dim List3(100) As Integerhas 101 elements (0 to 100). You can give a range,Dim AList(0 To 25), but the lower bound must be 0. - Java:
int[] list2; list2 = new int[5]; - Python can
print(List)a whole list at once. VB.NET and Java need a loop to print one element at a time.
Creating and accessing 2D arrays
To represent a game board of six rows and seven columns:
DECLARE <identifier> : ARRAY[<lBound1>:<uBound1>, <lBound2>:<uBound2>] OF <dataType> DECLARE Board : ARRAY[1:6, 1:7] OF INTEGER // 6 rows, 7 columns Board[3,4] ← 0 // sets the element in row 3 and column 4 to zero
Board = [[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]]
# or
Board = [[0 for i in range(7)] for j in range(6)]
# or
Board = [[0] * 7] * 6 # careful: see the teacher's note
Board[2][3] = 0 # row 3, column 4 (counting from 0)- In Python, a 2D array is a list of lists. The rows are numbered 0–5 and the columns 0–6; the upper value of a range is not included.
- VB.NET:
Dim Board(6, 7) As Integernumbers from 0 up to the given number, so it has one row and one column too many. But it can be easier to convert an algorithm if row 0 and column 0 are simply ignored:Board(3, 4) = 0. - Java:
int[][] board = new int[6][7];thenboard[2][3] = 0;
Board = [[0] * 7] * 6, makes six references to the same row. Setting Board[2][3] = 1 then changes column 3 in every row. Use the list-comprehension version for a real game board.🔬 Lab: the 6 × 7 game board
Tap a cell to drop a counter. See how the same cell is written in pseudocode (1-based) and in Python (0-based).
- Write program code for the pseudocode from Worked Example 13.04 in Chapter 13. First initialise the table, then output its contents.
- Write program code for the pseudocode from Worked Example 13.05 in Chapter 13.
📄 14.15 Text files
Writing to a text file
OPENFILE <filename> FOR WRITE // open the file for writing WRITEFILE <filename>, <stringValue> // write a line of text to the file CLOSEFILE <filename> // close file
FileHandle = open("SampleFile.TXT", "w")
FileHandle.write(LineOfText) # LineOfText must end with "\n"
FileHandle.close()Give the filename and the mode ('w' for write) when you call open. The line of text must end with the newline character "\n" to move to the next line of the file. If the file already exists, it is overwritten as soon as the file handle is assigned. VB.NET uses an IO.StreamWriter object (or FileOpen/PrintLine/FileClose). Java uses FileWriter and PrintWriter, and main must be declared throws IOException.
Reading from a text file
OPENFILE <filename> FOR READ // open file for reading READFILE <filename>, <stringVariable> // read a line of text from the file CLOSEFILE <filename> // close file
FileHandle = open("SampleFile.TXT", "r")
LineOfText = FileHandle.readline()
FileHandle.close()Mode 'r' is for read. VB.NET: IO.StreamReader. Java: FileReader plus BufferedReader; other library classes such as Scanner can also be used.
Appending to a text file
OPENFILE <filename> FOR APPEND // open file for append WRITEFILE <filename>, <stringValue> // write a line of text to the file CLOSEFILE <filename> // close file
FileHandle = open("SampleFile.TXT", "a")
FileHandle.write(LineOfText)
FileHandle.close()Mode 'a' is for append. In VB.NET the extra parameter True in New IO.StreamWriter("SampleFile.TXT", True) tells the system to append. Java: new FileWriter("SampleFile.TXT", true).
The end-of-file (EOF) marker
OPENFILE "Test.txt" FOR READ
WHILE NOT EOF("Test.txt") DO
READFILE "Test.txt", TextString
OUTPUT TextString
ENDWHILE
CLOSEFILE "Test.txt"FileHandle = open("Test.txt", "r")
LineOfText = FileHandle.readline()
while len(LineOfText) > 0: # "" means end of file
LineOfText = FileHandle.readline()
print(LineOfText)
FileHandle.close()Python has no explicit EOF function. Once the end-of-file marker is reached, the line read has length 0. VB.NET's EndOfStream becomes True at the end. In Java, the line read at the end is null.
FileHandle = open("Test.txt", "r")
LineOfText = FileHandle.readline()
while len(LineOfText) > 0: # "" means end of file
print(LineOfText, end='') # print FIRST...
LineOfText = FileHandle.readline() # ...then read the next line
FileHandle.close()Initialise Tally array
REPEAT
INPUT Choice // 1 for Reading, 2 for computer games,
// 3 for Sport, 4 for Programming, 5 for TV
// 0 to end input
Increment Tally[Choice]
UNTIL Choice = 0
FOR Index = 1 TO 5
OUTPUT Tally[Index]
NEXT Index- Write program code to declare and initialise the array
Tally : ARRAY[1:5] OF INTEGER. - Write program code to implement the algorithm above.
- Write program code to declare an array to store the hobby titles, and rewrite the FOR loop from part 2 so that each hobby title is output before its tally.
- Write program code to save the array data in a text file.
- Write program code to read the data from the text file back into the initialised array.
Increment Tally[Choice] when 0 is entered to stop. Tally is ARRAY[1:5], so Tally[0] is outside its bounds. Only increment when Choice <> 0.Model solution (all five parts) in Python
# 1-2: initialise, then run the algorithm (index 0 unused so Tally[1]..Tally[5] match)
Tally = [0, 0, 0, 0, 0, 0]
# 3: hobby titles in a second array
Hobbies = ["", "Reading books", "Play computer games", "Sport", "Programming", "Watching TV"]
Choice = -1
while Choice != 0: # Python has no REPEAT...UNTIL
Choice = int(input("1 Reading, 2 Games, 3 Sport, 4 Programming, 5 TV, 0 to end: "))
if 1 <= Choice <= 5: # don't count the 0 that ends input!
Tally[Choice] = Tally[Choice] + 1
for Index in range(1, 6):
print(Hobbies[Index], Tally[Index])
# 4: save the array to a text file, one value per line
FileHandle = open("Tally.txt", "w")
for Index in range(1, 6):
FileHandle.write(str(Tally[Index]) + "\n")
FileHandle.close()
# 5: read the file back into the initialised array
Tally = [0, 0, 0, 0, 0, 0]
FileHandle = open("Tally.txt", "r")
for Index in range(1, 6):
Tally[Index] = int(FileHandle.readline())
FileHandle.close()▶ Simulate Fred's survey
Each button is one student's INPUT Choice. Then save the array to a "file" and read it back.
📌 Summary
- Programming constructs in Python, VB.NET and Java include declaring and assigning constants and variables; the basic constructs of assignment, selection, repetition, input and output; and built-in data types and functions.
- Code should be commented where it helps understanding.
- Boolean expressions are needed for conditions.
- Subroutines (functions and procedures) are declared before the main program body.
- Calling a procedure is a program statement.
- Calling a function is done within an expression, for example an assignment.
- VB.NET and Java functions return exactly one value.
- Parameters can be passed to a subroutine. This is known as the interface.
- VB.NET passes parameters by value by default, but can return one or more values through parameters declared as reference parameters.
- In Python, parameters can only pass values into a subroutine. The only way to update a variable in the calling program is to return one or more values from a function.
- In Java, parameters can only pass values into a subroutine. The only way to update a variable in the calling program is to return one value from a function. Object parameters are always passed by reference.
- When a subroutine is defined, parameters are the placeholders for the values passed in.
- Arguments are the values passed to the subroutine when it is called.
🃏 Key-term flashcards
Tap a card to flip it.
✅ Quick quiz
📝 Exam-style questions
Write your answer first, then open the model answer. These are my own answers in 9618-style pseudocode, not official mark schemes. Other correct solutions exist.
DECLARE Ounces, Grams : INTEGER
DECLARE OzText : STRING
OUTPUT "Ounces Grams"
FOR Ounces ← 1 TO 30
Grams ← INT(Ounces * 28.35 + 0.5) // round to whole grams
OzText ← NUM_TO_STR(Ounces)
WHILE LENGTH(OzText) < 10 // pad to a fixed column width
OzText ← OzText & " "
ENDWHILE
OUTPUT OzText, Grams
NEXT OuncesMark points: heading output; FOR loop 1 to 30; ×28.35; rounding to a whole number (+0.5 then INT); conversion to string; padding to a fixed width so the columns line up; output inside the loop.
DECLARE UserID : STRING
DECLARE Valid : BOOLEAN
DECLARE i : INTEGER
DECLARE Ch : CHAR
INPUT "Enter user ID: " UserID
Valid ← (LENGTH(UserID) = 7)
IF Valid = TRUE
THEN
FOR i ← 1 TO 7
Ch ← MID(UserID, i, 1)
IF i <= 3
THEN
IF Ch < 'A' OR Ch > 'Z'
THEN
Valid ← FALSE // first three must be upper case letters
ENDIF
ELSE
IF Ch < '0' OR Ch > '9'
THEN
Valid ← FALSE // last four must be digits
ENDIF
ENDIF
NEXT i
ENDIF
IF Valid = TRUE
THEN
OUTPUT "UserID is valid"
ELSE
OUTPUT "UserID is not valid"
ENDIF🔬 Test it
PROCEDURE OutputTimesTable(BYVALUE n : INTEGER)
DECLARE i : INTEGER
FOR i ← 1 TO 10
OUTPUT i, " × ", n, " = ", i * n
NEXT i
ENDPROCEDUREMark points: procedure header with parameter and type; local loop variable; FOR 1 TO 10; correct calculation; correctly formatted output; ENDPROCEDURE.
FUNCTION isDivisible(x : INTEGER, y : INTEGER) RETURNS BOOLEAN
IF x MOD y = 0
THEN
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNCTIONA one-line body is also fine: RETURN (x MOD y = 0). Mark points: header with both parameters, RETURNS BOOLEAN, MOD, the comparison with 0, both returns, ENDFUNCTION.
PROCEDURE EggsIntoBoxes(BYVALUE NumberOfEggs : INTEGER,
BYREF NumberOfBoxes : INTEGER,
BYREF EggsLeftOver : INTEGER)
NumberOfBoxes ← NumberOfEggs DIV 6 // only full boxes
EggsLeftOver ← NumberOfEggs MOD 6 // what's left
ENDPROCEDURE
// called like this:
CALL EggsIntoBoxes(Eggs, Boxes, LeftOver)The key marks are for BYREF on the two output parameters (so the caller's variables are updated) and BYVALUE on the input. DIV gives full boxes and MOD gives eggs left over. For example, 20 eggs gives 3 boxes and 2 left over.
FUNCTION Matches(Reg : STRING, Pattern : STRING) RETURNS BOOLEAN
DECLARE i : INTEGER
DECLARE Ch : CHAR
FOR i ← 1 TO 7
Ch ← MID(Reg, i, 1)
IF MID(Pattern, i, 1) = "L"
THEN
IF Ch < 'A' OR Ch > 'Z'
THEN
RETURN FALSE
ENDIF
ELSE
IF Ch < '0' OR Ch > '9'
THEN
RETURN FALSE
ENDIF
ENDIF
NEXT i
RETURN TRUE
ENDFUNCTION
FUNCTION IsValidRegistration(Reg : STRING) RETURNS BOOLEAN
IF LENGTH(Reg) <> 7
THEN
RETURN FALSE
ENDIF
RETURN Matches(Reg, "LLNNLLL") OR Matches(Reg, "LLLNNLL")
ENDFUNCTIONWriting a helper function that checks against a pattern string avoids duplicating the loop. Writing two loops in one function is also acceptable.
🔬 Test it
Guru Jazzy · Cambridge AS & A Level Computer Science · Chapter 14 Programming and data representation · Figures from the Cambridge coursebook (Langfield & Duddell)