Pseudocode: the complete notes
Everything Cambridge O-Level pseudocode asks of you, in one place: data types, operators, selection, every loop, arrays, strings, functions, files, SQL, and fully worked 15-mark questions. Read it once, then use it as a reference right up to the exam.
Pseudocode is how you plan a program before you write real code. It uses plain, structured English with a fixed set of keywords so that any programmer can read your logic and turn it into any language. In your Paper 2 exam it is tested directly: you read it, trace it, correct it, and write your own. These notes follow the Cambridge conventions exactly, so the keywords and layout you see here are the ones that earn marks.
Choosing the right type is the first decision in any program because it tells the computer how much memory to reserve and what operations are allowed. Every piece of data you store has a type, and picking the wrong one is a common way to lose easy marks.
Declaring variables
Use DECLARE to tell the program a variable exists, and give it a type, before you use it. The pattern is always DECLARE name : TYPE.
DECLARE Colour : STRING DECLARE Age : INTEGER DECLARE Price : REAL DECLARE Flag : BOOLEAN DECLARE Grade : CHAR
Assigning values
Use the assignment arrow ← to put a value into a variable. Read it as "gets" or "is set to". Constants are fixed with CONSTANT and can never be reassigned.
Colour ← "red" Age ← 18 Price ← 9.99 Flag ← FALSE Grade ← 'A' CONSTANT Pi ← 3.142 // fixed, cannot change Pi ← 3.14159 // ERROR: cannot reassign a constant
INPUT and OUTPUT
INPUT reads a value the user types and stores it in a variable. OUTPUT displays text, variables, or both together separated by commas.
OUTPUT "Enter your name" // shows a prompt on screen INPUT Name // waits for the user to type OUTPUT "Hello, ", Name // text and variable together
Operators are the verbs of pseudocode: they combine values to produce new ones or to make decisions. They fall into three groups, arithmetic, comparison, and logical, and knowing exactly what each returns keeps your conditions correct.
| Operator | Meaning | Example | Result |
|---|---|---|---|
| + | Addition | 7 + 3 | 10 |
| - | Subtraction | 7 - 3 | 4 |
| * | Multiplication | 7 * 3 | 21 |
| / | Division (real result) | 7 / 2 | 3.5 |
| DIV | Integer division (drops decimal) | 7 DIV 2 | 3 |
| MOD | Remainder after division | 7 MOD 2 | 1 |
| = | Equal to | x = 5 | TRUE / FALSE |
| <> | Not equal to | x <> 5 | TRUE / FALSE |
| > < >= <= | Comparisons | Age >= 18 | TRUE / FALSE |
| AND | Both conditions must be TRUE | x > 0 AND x < 10 | TRUE / FALSE |
| OR | At least one must be TRUE | x = 0 OR x = 1 | TRUE / FALSE |
| NOT | Inverts a Boolean | NOT Flag | TRUE / FALSE |
| & | Join (concatenate) strings | "Hi " & Name | "Hi Ali" |
Order of operations
Pseudocode follows normal maths precedence. Brackets first, then * / DIV MOD, then + -, then comparisons, then logical operators. When in doubt, add brackets to make your intention obvious to the examiner.
Result ← 2 + 3 * 4 // 14, not 20 Result ← (2 + 3) * 4 // 20, brackets force the add first Valid ← Age >= 13 AND Age <= 19 // TRUE only for a teenager
String questions appear often because handling text well shows real understanding. Cambridge gives you a small set of built-in functions, and memorising exactly what each returns is worth easy marks. Note that string positions start at 1 in Cambridge pseudocode.
| Function | What it does | Example | Result |
|---|---|---|---|
| LENGTH(s) | Number of characters in s | LENGTH("Hello") | 5 |
| SUBSTRING(s,p,n) | n characters from position p | SUBSTRING("Computer",1,4) | "Comp" |
| UCASE(s) | Converts to upper case | UCASE("hi") | "HI" |
| LCASE(s) | Converts to lower case | LCASE("Hi") | "hi" |
| ROUND(x,n) | Rounds x to n decimal places | ROUND(3.146,2) | 3.15 |
| INT(x) | Whole-number part of x | INT(7.9) | 7 |
| RANDOM() | Random real from 0 to 1 | RANDOM() | 0.42... |
Worked string example: initials
This takes a first and last name and builds initials such as "A.J". It uses SUBSTRING to grab the first letter of each and & to join everything.
OUTPUT "Enter first name" INPUT First OUTPUT "Enter last name" INPUT Last Initials ← SUBSTRING(First, 1, 1) & "." & SUBSTRING(Last, 1, 1) OUTPUT UCASE(Initials)
Counting characters in a word
A classic task: loop through every position and count how many times a target letter appears. Notice how LENGTH sets the loop limit.
OUTPUT "Enter a word" INPUT Word Count ← 0 FOR Index ← 1 TO LENGTH(Word) IF SUBSTRING(Word, Index, 1) = 'a' THEN Count ← Count + 1 ENDIF NEXT Index OUTPUT "Letter a appears ", Count, " times"
Selection is how a program makes decisions, and IF is the most-used structure in the whole course. It runs one block of code when a condition is TRUE and, optionally, another when it is FALSE.
Basic structure
IF Age >= 18 THEN OUTPUT "Eligible to vote" ELSE OUTPUT "Not eligible" ENDIF
Nested IF (ELSE IF chain)
When there are more than two outcomes, chain conditions with ELSE IF. The program checks each in order and runs the first one that is TRUE, then skips the rest.
IF Hours > 50 THEN OUTPUT "Overtime bonus" ELSE IF Hours > 30 THEN OUTPUT "Normal salary" ELSE OUTPUT "Salary deducted" ENDIF
Practice questions
OUTPUT "Enter temperature" INPUT Temperature IF Temperature > 40 THEN OUTPUT "Too hot" ELSE OUTPUT "Pleasant weather" ENDIF
OUTPUT "Enter first number" INPUT Num1 OUTPUT "Enter second number" INPUT Num2 IF Num1 > Num2 THEN OUTPUT Num1 * 3 ELSE IF Num2 > Num1 THEN OUTPUT Num2 * 5 ELSE OUTPUT Num1 + Num2 ENDIF
When one variable can take many specific values, a long ELSE IF chain becomes hard to read. CASE OF is the clean alternative: it matches a single variable against a list of values and runs the matching branch. Use OTHERWISE to catch anything unexpected.
CASE OF Variable Value1 : OUTPUT "..." Value2 : OUTPUT "..." Value3 : OUTPUT "..." OTHERWISE : OUTPUT "Invalid input" ENDCASE
Example: simple calculator
OUTPUT "Enter two numbers" INPUT Num1, Num2 OUTPUT "Enter operator (+, -, *, /)" INPUT Operator CASE OF Operator '+' : OUTPUT Num1 + Num2 '-' : OUTPUT Num1 - Num2 '*' : OUTPUT Num1 * Num2 '/' : OUTPUT Num1 / Num2 OTHERWISE : OUTPUT "Invalid operator" ENDCASE
Example: grade to points
OUTPUT "Enter grade (A/B/C/D/F)" INPUT Grade CASE OF Grade 'A' : OUTPUT "4.0 points" 'B' : OUTPUT "3.0 points" 'C' : OUTPUT "2.0 points" 'D' : OUTPUT "1.0 points" 'F' : OUTPUT "0.0 points" OTHERWISE : OUTPUT "Invalid grade" ENDCASE
A FOR loop repeats a block a known number of times, so reach for it whenever you can say up front "do this exactly N times". A counter variable is created, increased automatically each pass, and the loop ends after the final value.
FOR Index ← 1 TO 10 // code here runs 10 times NEXT Index // Counting down with STEP FOR Index ← 10 TO 1 STEP -1 OUTPUT Index NEXT Index // Even numbers only with STEP 2 FOR Index ← 2 TO 20 STEP 2 OUTPUT Index NEXT Index
Practice: sum and average of 20 numbers
Sum ← 0 FOR Index ← 1 TO 20 OUTPUT "Enter a number" INPUT Num Sum ← Sum + Num NEXT Index OUTPUT "Sum: ", Sum OUTPUT "Average: ", Sum / 20
Practice: 7-day temperature monitor
This combines a FOR loop with selection and three counters, a pattern that appears again and again in exams.
HotDays ← 0 NiceDays ← 0 ColdDays ← 0 FOR Index ← 1 TO 7 OUTPUT "Enter temperature for day ", Index INPUT Temp IF Temp > 30 THEN HotDays ← HotDays + 1 ELSE IF Temp >= 20 THEN NiceDays ← NiceDays + 1 ELSE ColdDays ← ColdDays + 1 ENDIF NEXT Index OUTPUT "Hot days: ", HotDays OUTPUT "Nice days: ", NiceDays OUTPUT "Cold days: ", ColdDays
A WHILE loop repeats as long as a condition stays TRUE, which makes it the right choice when you do not know in advance how many passes are needed. Because the test comes first, the body may run zero times if the condition starts FALSE.
Index ← 1 WHILE Index <= 10 OUTPUT Index Index ← Index + 1 ENDWHILE
Example: sum until the user enters 0
Sum ← 0 OUTPUT "Enter a number (0 to stop)" INPUT Num WHILE Num <> 0 Sum ← Sum + Num OUTPUT "Enter a number (0 to stop)" INPUT Num ENDWHILE OUTPUT "Total: ", Sum
Example: password login (3 attempts)
Flag ← FALSE Tries ← 3 WHILE Flag = FALSE AND Tries > 0 OUTPUT "Attempts remaining: ", Tries OUTPUT "Enter password" INPUT Password IF Password = "hello123" THEN Flag ← TRUE ENDIF Tries ← Tries - 1 ENDWHILE IF Flag = TRUE THEN OUTPUT "Access granted" ELSE OUTPUT "Access denied" ENDIF
Example: factorial (5! = 120)
OUTPUT "Enter a number" INPUT Num Index ← 1 Factorial ← 1 WHILE Index <= Num Factorial ← Factorial * Index Index ← Index + 1 ENDWHILE OUTPUT "Factorial: ", Factorial
REPEAT UNTIL runs the body first and checks the condition afterwards, so it always executes at least once. That makes it the natural fit for input validation, where you must ask for a value before you can judge whether it is acceptable.
WHILE pre-condition
Checks the condition BEFORE running. May run zero times. Loops WHILE the condition is TRUE.
REPEAT UNTIL post-condition
Checks the condition AFTER running. Always runs at least once. Loops UNTIL the condition becomes TRUE.
Input validation
// keep asking until a valid month is entered REPEAT OUTPUT "Enter month (1-12)" INPUT Month UNTIL Month >= 1 AND Month <= 12
Example: even and odd sums (1 to 10)
OddSum ← 0 EvenSum ← 0 Index ← 1 REPEAT IF Index MOD 2 = 0 THEN EvenSum ← EvenSum + Index ELSE OddSum ← OddSum + Index ENDIF Index ← Index + 1 UNTIL Index > 10 OUTPUT "Even sum: ", EvenSum OUTPUT "Odd sum: ", OddSum
Most Paper 2 answers are built from three small, reusable patterns. Learn them as templates and you can assemble almost any question quickly and correctly. They matter because examiners reward the technique, not just the final answer.
Totalling and counting
A total variable starts at 0 and grows by a value each pass. A counter starts at 0 and grows by 1 each time something is true. Almost every "find the average" or "how many" task uses one or both.
Total ← 0 Count ← 0 FOR Index ← 1 TO 30 INPUT Mark Total ← Total + Mark // running total IF Mark >= 50 THEN Count ← Count + 1 // count the passes ENDIF NEXT Index OUTPUT "Average: ", Total / 30 OUTPUT "Number passing: ", Count
Finding highest and lowest
Set the tracker to the first value (or a safe extreme), then compare every later value against it. Never start "highest" at 0, because that fails if all values are negative.
INPUT Num Highest ← Num Lowest ← Num FOR Index ← 2 TO 10 INPUT Num IF Num > Highest THEN Highest ← Num ENDIF IF Num < Lowest THEN Lowest ← Num ENDIF NEXT Index OUTPUT "Highest: ", Highest, " Lowest: ", Lowest
Range check vs length check
Validation confirms data is sensible before the program uses it. The two most-tested kinds are a range check (a number inside limits) and a length check (a string of the right size).
// Range check: percentage 0 to 100 REPEAT OUTPUT "Enter percentage (0-100)" INPUT Percent UNTIL Percent >= 0 AND Percent <= 100 // Length check: PIN must be exactly 4 characters REPEAT OUTPUT "Enter a 4-digit PIN" INPUT Pin UNTIL LENGTH(Pin) = 4
An array lets you store many values of the same type under one name, which is essential once you are handling lists of data such as scores or names. Each value sits at a numbered position called an index, and you reach it with Name[index].
Declaring, assigning, accessing
// 10 integers, indexed 1 to 10 DECLARE Scores : ARRAY[1:10] OF INTEGER // assign directly Scores[1] ← 85 Scores[2] ← 92 // fill every element with 0 FOR Index ← 1 TO 10 Scores[Index] ← 0 NEXT Index // take input into the array FOR Index ← 1 TO 10 OUTPUT "Enter score" INPUT Scores[Index] NEXT Index
Linear search (efficient)
A linear search checks elements one by one. The efficient version stops the moment it finds the value, instead of scanning to the end for nothing.
FUNCTION LinearSearch(ValToFind : INTEGER) RETURNS BOOLEAN Found ← FALSE Index ← 1 REPEAT IF Scores[Index] = ValToFind THEN Found ← TRUE ELSE Index ← Index + 1 ENDIF UNTIL Index > 10 OR Found = TRUE RETURN Found ENDFUNCTION
Find the largest value
DECLARE Values : ARRAY[1:5] OF INTEGER FOR Index ← 1 TO 5 OUTPUT "Enter a value" INPUT Values[Index] NEXT Index Largest ← Values[1] // start with the first element FOR Index ← 2 TO 5 IF Values[Index] > Largest THEN Largest ← Values[Index] ENDIF NEXT Index OUTPUT "Largest value: ", Largest
Bubble sort (efficient)
Bubble sort repeatedly compares neighbours and swaps them if they are out of order, so the largest value "bubbles" to the end each pass. The efficient version stops early once a full pass makes no swaps.
// sorts Scores[1:10] into ascending order UpperBound ← 10 REPEAT UpperBound ← UpperBound - 1 Swap ← FALSE FOR Index ← 1 TO UpperBound IF Scores[Index] > Scores[Index + 1] THEN Temp ← Scores[Index] Scores[Index] ← Scores[Index + 1] Scores[Index + 1] ← Temp Swap ← TRUE ENDIF NEXT Index UNTIL UpperBound = 1 OR Swap = FALSE
A 2D array is a table of rows and columns, perfect for grids, timetables, or one record per row. You need two indexes to reach a single cell: Array[row, column]. Nested loops are how you visit every cell.
Declaring and accessing
// 5 students, 3 columns (e.g. three subject marks) DECLARE Marks : ARRAY[1:5, 1:3] OF INTEGER Marks[1, 1] ← 85 // student 1, subject 1 Marks[2, 3] ← 70 // student 2, subject 3
Input and output with nested loops
The outer loop moves down the rows, and for each row the inner loop sweeps across the columns. Change the inner loop and the outer stays put.
// taking input FOR Row ← 1 TO 5 FOR Col ← 1 TO 3 OUTPUT "Enter mark for student ", Row, " subject ", Col INPUT Marks[Row, Col] NEXT Col NEXT Row // outputting values FOR Row ← 1 TO 5 FOR Col ← 1 TO 3 OUTPUT Marks[Row, Col] NEXT Col NEXT Row
StudentData: search by ID, output name
A very common exam shape: a table where column 1 holds an ID and column 2 holds a name. Search the ID column, then read across to the name.
OUTPUT "Enter the student ID" INPUT Id Found ← FALSE Row ← 1 REPEAT IF StudentData[Row, 1] = Id THEN Found ← TRUE ELSE Row ← Row + 1 ENDIF UNTIL Row > 1000 OR Found = TRUE IF Found = TRUE THEN OUTPUT "Name: ", StudentData[Row, 2] ELSE OUTPUT "ID not found" ENDIF
Subroutines let you name a block of code once and reuse it, which keeps programs short and readable. Cambridge splits them into two kinds, and telling them apart is a guaranteed exam question.
FUNCTION returns a value
Takes parameters, does work, and hands back one result with RETURN. You store or use that result, e.g. g ← GradeCalc(...).
PROCEDURE no return
Takes parameters and performs an action such as printing, but returns nothing. You call it as a statement on its own line.
FUNCTION: grade calculator
FUNCTION GradeCalc(M1 : INTEGER, M2 : INTEGER, M3 : INTEGER) RETURNS CHAR Total ← M1 + M2 + M3 Percent ← Total / 3 IF Percent >= 90 THEN Grade ← 'A' ELSE IF Percent >= 80 THEN Grade ← 'B' ELSE IF Percent >= 70 THEN Grade ← 'C' ELSE IF Percent >= 60 THEN Grade ← 'D' ELSE Grade ← 'F' ENDIF RETURN Grade ENDFUNCTION // calling the function OUTPUT "Enter marks for 3 subjects" INPUT S1, S2, S3 Result ← GradeCalc(S1, S2, S3) OUTPUT "Your grade is: ", Result
PROCEDURE: draw a triangle of stars
PROCEDURE DrawTriangle(Size : INTEGER) FOR Row ← 1 TO Size FOR Col ← 1 TO Row OUTPUT "*" NEXT Col OUTPUT "" // move to a new line NEXT Row ENDPROCEDURE // calling the procedure CALL DrawTriangle(5) // prints a 5-row triangle
Files let a program store data permanently, so information survives after the program closes. Without files, everything held in variables is lost the moment the program ends. Cambridge pseudocode has two modes: READ and WRITE.
Writing to a file
OPENFILE "data.txt" FOR WRITE WRITEFILE "data.txt", "This is line one" WRITEFILE "data.txt", "This is line two" CLOSEFILE "data.txt"
Reading until end of file
EOF("file") returns TRUE once the last line has been read, so a WHILE loop over NOT EOF reads every line without needing to know how many there are.
OPENFILE "data.txt" FOR READ WHILE NOT EOF("data.txt") READFILE "data.txt", OneLine OUTPUT OneLine ENDWHILE CLOSEFILE "data.txt"
Example: split scores into high / medium / low files
This reads one source file and writes each score to one of three destination files based on its value, a realistic task that combines files, a loop, and selection.
OPENFILE "exam_scores.txt" FOR READ OPENFILE "high.txt" FOR WRITE OPENFILE "medium.txt" FOR WRITE OPENFILE "low.txt" FOR WRITE WHILE NOT EOF("exam_scores.txt") READFILE "exam_scores.txt", Score IF Score >= 80 THEN WRITEFILE "high.txt", Score ELSE IF Score >= 50 THEN WRITEFILE "medium.txt", Score ELSE WRITEFILE "low.txt", Score ENDIF ENDWHILE CLOSEFILE "exam_scores.txt" CLOSEFILE "high.txt" CLOSEFILE "medium.txt" CLOSEFILE "low.txt"
SQL (Structured Query Language) pulls data out of a database table. It is a small part of the syllabus but a reliable source of marks, because the whole topic rests on just four keywords used in a fixed order.
| Keyword | What it does | Required? |
|---|---|---|
| SELECT | Choose which columns to show. Use * for all. | Always |
| FROM | Which table to read from. | Always |
| WHERE | Filter the rows on a condition. | Optional |
| ORDER BY | Sort the results, ASC low to high or DESC high to low. | Optional |
Examples
-- Show all data SELECT * FROM STUDENT -- Year 11 students scoring above 70, highest score first SELECT FirstName, LastName, Score FROM STUDENT WHERE YearGroup = 11 AND Score > 70 ORDER BY Score DESC -- Everyone in house Blue, sorted by surname A to Z SELECT FirstName, LastName FROM STUDENT WHERE HouseColour = 'Blue' ORDER BY LastName ASC -- All grade A students SELECT * FROM STUDENT WHERE Grade = 'A'
Question 1: cricket league points system
Twelve clubs. Track wins, draws, and losses. Points are Win = 12, Draw = 5, Loss = 0. Find and output the club or clubs with the most points.
// Step 1: input and validate number of matches (max 22) REPEAT OUTPUT "Enter number of matches played (max 22)" INPUT Matches UNTIL Matches >= 1 AND Matches <= 22 // Step 2: input club names and results, validated FOR Index ← 1 TO 12 OUTPUT "Enter name of club ", Index INPUT Clubs[Index] REPEAT OUTPUT "Enter matches won, drawn, lost" INPUT Won, Drawn, Lost IF (Won + Drawn + Lost) <> Matches THEN OUTPUT "Error: totals must add up to ", Matches ENDIF UNTIL (Won + Drawn + Lost) = Matches Statistics[Index, 1] ← Won Statistics[Index, 2] ← Drawn Statistics[Index, 3] ← Lost // Step 3: calculate points Points[Index] ← (Won * 12) + (Drawn * 5) NEXT Index // Step 4: find the highest points total Highest ← -1 FOR Index ← 1 TO 12 IF Points[Index] > Highest THEN Highest ← Points[Index] ENDIF NEXT Index // Step 5: output every club on the highest points (handles ties) FOR Index ← 1 TO 12 IF Points[Index] = Highest THEN OUTPUT "Winner: ", Clubs[Index] OUTPUT "Wins: ", Statistics[Index, 1] OUTPUT "Points: ", Highest ENDIF NEXT Index
Question 2: grid treasure hunt game
A 5 by 5 grid. Place 'X' at a random cell that is not [1,1]. The player starts at [1,1] and has 10 moves to reach X using W, A, S, D. Validate moves so the player cannot leave the grid.
// Step 1: fill the grid with empty strings FOR Row ← 1 TO 5 FOR Col ← 1 TO 5 Grid[Row, Col] ← "" NEXT Col NEXT Row // Step 2: place 'X' at a random cell, but not [1,1] REPEAT Xrow ← INT(RANDOM() * 5) + 1 Xcol ← INT(RANDOM() * 5) + 1 UNTIL Xrow <> 1 OR Xcol <> 1 Grid[Xrow, Xcol] ← 'X' // Step 3: set up the player and move counter PlayerRow ← 1 PlayerCol ← 1 MoveCount ← 0 Win ← FALSE // Step 4: game loop, up to 10 moves REPEAT OUTPUT "Position [", PlayerRow, ",", PlayerCol, "] Moves left: ", 10 - MoveCount OUTPUT "W=Up S=Down A=Left D=Right" INPUT Move Move ← UCASE(Move) Error ← FALSE TempR ← PlayerRow TempC ← PlayerCol CASE OF Move 'W' : TempR ← PlayerRow - 1 'S' : TempR ← PlayerRow + 1 'A' : TempC ← PlayerCol - 1 'D' : TempC ← PlayerCol + 1 OTHERWISE : Error ← TRUE ENDCASE // validate the move stays inside the grid IF TempR < 1 OR TempR > 5 OR TempC < 1 OR TempC > 5 THEN Error ← TRUE OUTPUT "Move out of bounds, try again" ENDIF IF Error = FALSE THEN PlayerRow ← TempR PlayerCol ← TempC MoveCount ← MoveCount + 1 ENDIF // check for a win IF Grid[PlayerRow, PlayerCol] = 'X' THEN Win ← TRUE OUTPUT "You win! Found it in ", MoveCount, " moves." ENDIF UNTIL Win = TRUE OR MoveCount = 10 IF Win = FALSE THEN OUTPUT "You lose. The X was at [", Xrow, ",", Xcol, "]" ENDIF
Two students can write the same logic and score differently. The difference is usually technique: closing every structure, naming things clearly, and reading the question properly. This section collects the habits that turn a good answer into a full-mark one.
Close every structure with its partner
Each opening keyword has a matching closer. Miss one and the marker cannot follow your logic. Memorise these pairs.
| Opens with | Closes with |
|---|---|
| IF | ENDIF |
| CASE OF | ENDCASE |
| FOR | NEXT |
| WHILE | ENDWHILE |
| REPEAT | UNTIL |
| PROCEDURE | ENDPROCEDURE |
| FUNCTION | ENDFUNCTION |
Trace tables: show your working
When a question says "complete the trace table", run the code by hand and write down each variable every time it changes. Take this snippet and its trace.
Total ← 0 FOR Index ← 1 TO 3 Total ← Total + Index NEXT Index OUTPUT Total
| Index | Total | Output |
|---|---|---|
| 1 | 1 | |
| 2 | 3 | |
| 3 | 6 | 6 |
The mistakes that cost marks most often
- Writing END IF as two words, or forgetting ENDWHILE and NEXT entirely.
- Using = for both assignment and comparison in a way that confuses the reader. Prefer ← for assignment.
- Starting Highest at 0 instead of the first data value, which breaks with negative data.
- Forgetting the second INPUT inside a WHILE loop, causing an endless loop on the same value.
- Missing CLOSEFILE, or opening a file for the wrong mode.
- Putting numbers in quotes, or text without quotes, in SQL and CASE branches.
- Not initialising a total or counter to 0 before the loop.
A reliable answer plan
- Read the whole question and underline every separate requirement.
- Declare and initialise your variables and arrays first.
- Deal with input and validation before any processing.
- Write the loop or logic, adding a comment per requirement.
- Output results with clear, labelled messages, not bare numbers.
- Trace your own code with one sample input to check it works.
