Additional Programming Techniques
Strings, arrays, file handling, SQL, subroutines and random numbers. This is the widest single topic on Paper 2 and the one with the most easy marks available.
String manipulation
| Operation | OCR reference language | Python |
|---|---|---|
| Length | name.length | len(name) |
| Substring | name.substring(2,3) | name[2:5] |
| Uppercase | name.upper | name.upper() |
| Lowercase | name.lower | name.lower() |
| Left characters | name.left(3) | name[:3] |
| Right characters | name.right(3) | name[-3:] |
| Join | first + " " + last | first + " " + last |
"Computing".substring(3,4) starts at index 3 and takes 4 characters, giving puti. Python slicing takes a start and an END index, so "Computing"[3:7] also gives puti. Read the question carefully to see which is being used.
Common patterns
# Build a username from a name
first = "Aisha"
last = "Khan"
username = (first[0] + last).lower() # akhan
# Count the vowels in a word
word = input("Enter a word: ")
count = 0
for letter in word.lower():
if letter in "aeiou":
count = count + 1
print("Vowels:", count)
# Reverse a string
print(word[::-1])
# Check a palindrome
clean = word.lower().replace(" ", "")
if clean == clean[::-1]:
print("Palindrome")- Every character has an index. The first is 0, and negative indexes count back from the end.
- A slice [a:b] runs from index a up to, but not including, b. Leave b out to go to the end.
- [-1] is the last character.
- Functions and methods build and search strings, and each one gives back a new string.
- upper() makes every letter a capital.
- strip() removes spaces from both ends.
- replace() swaps every match for something else.
- split() breaks a string into a list.
- join() builds a string from a list.
- find() gives the position of the first match, or -1 if there is none.
- A method returns a new string. The original is never changed unless you assign the result.
Arrays and lists
An array stores many values of the same type under one name, accessed by an index starting at 0.
scores = [12, 45, 3, 78, 20]
print(scores[0]) # 12, the first item
print(scores[4]) # 20, the last item
print(len(scores)) # 5
scores[2] = 99 # change the third item
scores.append(60) # add to the endWorking through an array
total = 0
highest = scores[0]
for value in scores:
total = total + value
if value > highest:
highest = value
print("Total:", total)
print("Average:", total / len(scores))
print("Highest:", highest)Notice highest is initialised to the first element, not to 0. Initialising to 0 breaks if all the values are negative.
Two dimensional arrays
A 2D array is a grid, accessed with two indexes: row then column.
board = [["X", "O", "X"],
["O", "X", "O"],
["X", "O", "X"]]
print(board[1][2]) # row 1, column 2, which is "O"
for row in board:
for cell in row:
print(cell, end=" ")
print()board[1][2] means row 1, column 2. Getting these the wrong way round is a classic exam error, especially in non square grids.
- The list holds its items in order, and the first locker is number 0.
- append() puts a new item on the end, so the list grows.
- Assign to an index to replace what is there. The old value is gone.
- scores[2] opens locker 2. len(scores) counts the lockers, so the last index is one less.
File handling
Programs need to store data between runs, and that means reading from and writing to files.
# Writing to a file
file = open("scores.txt", "w") # "w" overwrites the whole file
file.write("Aisha,42
")
file.write("Ben,37
")
file.close()
# Appending, which adds without deleting what is there
file = open("scores.txt", "a")
file.write("Chris,55
")
file.close()
# Reading the whole file line by line
file = open("scores.txt", "r")
for line in file:
parts = line.strip().split(",")
name = parts[0]
score = int(parts[1])
print(name, "scored", score)
file.close()The three modes
| Mode | Meaning |
|---|---|
"r" | Read. Fails if the file does not exist. |
"w" | Write. Creates the file, and erases everything already in it. |
"a" | Append. Creates the file if needed, and adds to the end. |
If a question asks you to add a record without losing existing data, you must use append mode. This is a common mark.
Always close the file when finished, so that data is properly written and the file is released.
OCR reference language
myFile = open("scores.txt")
while NOT myFile.endOfFile()
print(myFile.readLine())
endwhile
myFile.close()- r reads. The file is only looked at, and it must already exist.
- w writes. Everything already in the file is erased first.
- a appends. New lines go on the end and the old ones are kept.
- with closes the file for you, and \n ends a line.
SQL
SQL, Structured Query Language, is used to search and manipulate data in a database. J277 requires SELECT, FROM and WHERE.
SELECT which columns you want FROM which table WHERE which rows to include
Examples
Given a table called Students:
| StudentID | Name | Year | Grade |
|---|---|---|---|
| 1 | Aisha | 11 | 9 |
| 2 | Ben | 10 | 6 |
| 3 | Chloe | 11 | 8 |
Select everything:
SELECT * FROM StudentsSelect specific columns:
SELECT Name, Grade FROM StudentsSelect with a condition:
SELECT Name FROM Students WHERE Year = 11Multiple conditions:
SELECT Name FROM Students WHERE Year = 11 AND Grade >= 8Text values need quotation marks, numbers do not:
SELECT * FROM Students WHERE Name = 'Aisha'SELECT * returns every column. If the question asks only for names, use SELECT Name or you may lose the mark for precision.
- Each clause has a job: SELECT picks columns, FROM names the table, WHERE picks rows, ORDER BY sorts.
- WHERE keeps the rows that meet the condition and drops the rest.
- The result has only the selected columns, in the order asked for.
Subroutines and random numbers
Subroutines
A subroutine is a named block of code that performs a specific task and can be called from anywhere in a program.
def calculate_area(width, height):
return width * height # a FUNCTION, it returns a value
def show_welcome(name):
print("Welcome,", name) # a PROCEDURE, it returns nothing
area = calculate_area(5, 3) # area is 15
show_welcome("Aisha")Parameters are the variables listed in the definition. Arguments are the actual values passed in when it is called.
Why subroutines matter
- Avoid repetition. Write the code once and call it many times.
- Easier to test. Each subroutine can be tested on its own.
- Easier to maintain. Fix a bug in one place rather than in ten copies.
- Reusable in other programs.
- Support decomposition, since each sub problem becomes a subroutine.
- Improve readability, because a well named call explains itself.
Local and global variables
A local variable exists only inside the subroutine where it is created. A global variable is available throughout the whole program.
Local variables are preferred because they cannot be changed accidentally by other parts of the program, and their memory is freed when the subroutine finishes.
Random numbers
import random
dice = random.randint(1, 6) # a whole number from 1 to 6 inclusive
card = random.choice(["A", "K", "Q"]) # a random item from a listdice = random(1, 6)Random numbers are used in games, simulations, shuffling, sampling and generating test data.
- Define it once with def, naming the parameters it will be given.
- Call it with arguments. They fill the parameters, w = 3 and h = 4.
- return hands the result back to the line that called it.
- A procedure does a job. A function also gives a value back.
Key terms you must be able to define
- Array
- A data structure holding many values of the same type under one name, accessed by index.
- Index
- The position of an item within an array, counting from 0.
- 2D array
- An array of arrays, forming a grid accessed by row and column.
- Subroutine
- A named block of code that performs a specific task and can be called from elsewhere.
- Parameter
- A variable listed in a subroutine definition that receives a value when it is called.
- Argument
- The actual value passed into a subroutine when it is called.
- Local variable
- A variable that only exists within the subroutine in which it is declared.
- Global variable
- A variable available to every part of the program.
- Concatenation
- Joining strings together end to end.
- SQL
- Structured Query Language, used to search and manipulate data in a database.
- Append mode
- Opening a file so that new data is added to the end without erasing existing content.
Flashcards
Say the definition out loud before you flip the card. Retrieving it from memory is what builds recall, reading it again is not.
Reach the top grade on this topic
This topic covers a lot of ground, so target the marks that are most reliably available.
SQL is nearly free marks. Three keywords, one structure. Learn SELECT ... FROM ... WHERE ... and practise ten queries. Quote text values, do not quote numbers, and only select the columns you were asked for.
File modes matter. If the question says add a record without losing existing data, the answer is append mode. Write mode erases the file.
Explain subroutines by benefit, not definition. "A subroutine avoids repeating the same code, so if the calculation changes it only has to be edited in one place, which reduces the chance of introducing errors."
Initialise from the data, not from zero. When finding a maximum or minimum in an array, start from the first element. This is a favourite exam trap.
- Write a SELECT query with a WHERE clause for any given table
- Read a file line by line and split each line into fields
- Write a function and call it, and explain why it is a function not a procedure
- Loop through a 2D array using row and column indexes in the right order
Mistakes that cost marks here
- Opening a file in write mode when the question requires existing data to be kept.
- Forgetting to close a file after use.
- Using SELECT * when the question asked for specific columns.
- Putting quotation marks around a number in an SQL WHERE clause.
- Getting row and column the wrong way round in a 2D array.
- Initialising a maximum to 0 rather than to the first element of the array.
- Forgetting that array indexes start at 0, so the last index is length minus 1.
Almost every real program spends most of its time manipulating strings and reading files. The glamorous algorithms get the attention, but text processing is what software actually does all day.
Knowledge check
"Programming"[0:4] produce in Python?data has 8 elements. What is the index of the last element?grid, how would you access the item in row 2, column 0?random.randint(1, 6) return?Exam-style questions
Five written questions in the style of the real paper. Write a full answer, then let the marker check it against the mark scheme.
- LUses SELECT with the correct columns Name and Grade
- LUses FROM with the correct table name
- LUses WHERE with the correct condition
SELECT Name, Grade FROM Students WHERE Grade >= 7 The SELECT clause names the two columns required rather than using an asterisk, FROM names the table being queried, and WHERE restricts the rows returned to those where the Grade column holds a value of 7 or above. No quotation marks are used around 7 because it is a number, not text.
- LCode that is needed in several places is written only once
- LIf a change is needed it is made in one place, reducing errors
- LEach subroutine can be tested independently
- LPrograms are easier to read and understand, and subroutines support decomposition
The first benefit is the removal of duplication. Code that is needed in several parts of a program can be written once as a subroutine and then called wherever it is needed, which makes the program shorter. More importantly, if that code ever needs correcting or updating, the change only has to be made in one place, rather than finding and editing every copy, which greatly reduces the risk of leaving an old version behind and introducing a bug. The second benefit is that subroutines make a program much easier to develop and test. Each subroutine handles one clearly defined task, so it can be tested on its own with a range of inputs until it is known to work correctly, and different programmers can develop different subroutines at the same time. This also makes the main program far easier to read, because a well named call such as calculateTotalCost explains what is happening without the reader needing to see the detail.
- LWrite mode erases the existing contents of the file
- LAll previous high scores would therefore be lost
- LAppend mode adds the new score to the end while keeping existing data
Opening a file in write mode causes the existing contents of that file to be erased before anything new is written, so every high score already stored would be permanently lost as soon as a single new score was saved. Append mode instead opens the file so that anything written is added to the end, leaving all the existing content untouched. Since the purpose of a high score table is to accumulate results over time, append mode is the correct choice.
- LOpens the file for reading
- LUses a loop to process each line
- LRemoves the newline character or otherwise cleans the line
- LTests whether the first character is A
- LOutputs matching names and closes the file
file = open("names.txt", "r") for line in file: name = line.strip() if name[0].upper() == "A": print(name) file.close() The file is opened in read mode and each line is processed in turn. The strip method removes the newline character from the end of each line so that the name is clean. The first character of the name is converted to uppercase and compared with A, so that names beginning with either a capital or a lowercase a are matched, and matching names are printed. The file is closed once every line has been processed.
- LA local variable only exists inside the subroutine where it is declared
- LA global variable is accessible throughout the whole program
- LLocal variables cannot be changed accidentally by other parts of the program
- LMemory used by a local variable is freed when the subroutine ends
A local variable is declared inside a subroutine and only exists while that subroutine is running, so it cannot be seen or changed by any code outside it. A global variable is declared outside all subroutines and is accessible from anywhere in the program, so any part of the code can read or modify it. Local variables are usually preferred because their limited scope prevents them being altered accidentally by unrelated parts of the program, which removes a very common and hard to trace source of bugs, and it also means two subroutines can safely use the same variable name without interfering with each other. In addition, the memory a local variable occupies is released as soon as the subroutine finishes, whereas a global variable takes up memory for the entire time the program runs.