It is mid-September 2026, school started again a couple of weeks ago, and in the Year 3 classes of the technical institutes (Italian technical secondary schools), in the Computer Science specialisation (articolazione Informatica), the computer science programme is picking up from a precise point: selection and loops, then arrays, then functions and recursion. The first serious test arrives in six to eight weeks, almost always between the end of October and mid-November, and it changes format compared with the first two years: no longer just a written theory paper, but a practical exam at the PC together with the written theory paper.
It is this change of format, more than the content itself, that catches by surprise those who prepare by studying only the theory by heart. In Years 1 and 2 it was enough to understand how an if or a single loop works. In Year 3 the programme asks you to design a program that solves a problem with several pieces of data at once, and the test checks it by making you write code at the computer, not just describe it on paper.
What the Year 3 test really asks
In the first two years, computer science works with variables, types, operators and simple control structures: one problem, one sequence of instructions, at most a single loop. In Year 3 the jump is sharp, because the teacher introduces arrays and functions precisely to handle several pieces of data together and to split a problem into smaller pieces. The practical exam that arrives between the end of October and mid-November generally asks for three things together:
- a program that uses a nested loop over a structure with several rows of data — a table, a matrix, a list with several fields;
- an array filled, read and modified through a function to which it is passed as a parameter;
- often a simple recursive function, such as the factorial, to introduce the idea that a function can call itself.
The written theory paper that goes with the practical exam asks you to follow the program line by line: how many times a nested loop runs, what the array contains at a certain point of the execution, what a function returns with certain arguments. This is where you can see who has only copied the syntax from an example and who has really understood what the program does while it runs.
In the same period, in Systems and Networks (a separate subject), conversions between binary and hexadecimal arrive too: it is a different topic from this one — here we concentrate on loops, arrays and functions — but it is worth knowing, because the slips there (a forgotten digit, a swapped base) are the same kind of mistake we see here with indexes and loop limits.
The mistakes that cost marks
1. Confusing the number of iterations with the final index. A loop for (int i = 0; i < n; i++) runs exactly n times, with i going from 0 to n-1. The most common mistake is to write i <= n: the loop runs once more and, on an array declared with n elements, reads or writes out of bounds. It is the classic off-by-one error, and in C it gives no warning at compile time: the program compiles, sometimes runs without crashing, and the result is wrong all the same.
2. Nested loop with the indexes swapped. On an n × m matrix, writing matrix[j][i] instead of matrix[i][j] compiles and runs without errors — but the result is wrong, because you are reading a column instead of a row. Before writing the inner loop, it is worth fixing in writing what i and j represent (row or column) and sticking to that choice for the whole exercise.
3. Passing an array to a function and expecting it to stay intact. In C an array passed as a parameter is not copied: the function works on the caller’s original array. Anyone who expects the array to stay as it was after the call loses marks both in the practical exam and in the written theory paper, where you are often asked explicitly “what does the array contain after this call?”.
4. Missing or wrong base case in recursion. A recursive function without a clear exit condition calls itself without stopping, until the program crashes because the memory set aside for calls runs out (stack overflow). The most insidious mistake is not the total absence of the base case, but a base case that triggers at the wrong value — for example stopping at n == 1 in a sequence that, the way the recursive call is written, never meets that value.
The method, step by step
Before writing code for an exercise with a nested loop, an array or recursion, it is worth following the same order every time:
- Write in words what the program must do, in one sentence, before the code. If you can’t say it in words, you won’t write it correctly in C.
- Draw the data structure on paper: for an array, a row of boxes numbered from
0; for a matrix, a grid with labelled rows and columns. - Write the loop header last, not first: decide where the index starts and where it must stop, then write
foraccordingly — not the other way round. - For each function, write the signature first (return type, name, parameters) and ask yourself: must it modify the caller’s data or return a new result? The answer decides whether to pass the array in order to modify it in place or to compute and return a value.
- For recursion, write the base case before the general case, and check by hand, with a small value, that the sequence of calls really reaches that base case.
Three worked examples
Exercise 1 — nested loop: sum by row of a matrix.
Given a 3×4 matrix of integers, write a program that calculates and prints the sum of the elements of each row.
#include <stdio.h>
#define ROWS 3
#define COLUMNS 4
int main(void) {
int matrix[ROWS][COLUMNS] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int i = 0; i < ROWS; i++) {
int sum = 0;
for (int j = 0; j < COLUMNS; j++) {
sum += matrix[i][j];
}
printf("Row %d sum: %d\n", i, sum);
}
return 0;
}
The outer loop runs through the rows (i from 0 to ROWS-1), the inner loop runs through the columns of that row (j from 0 to COLUMNS-1) and accumulates in sum. The detail that those who get this exercise wrong almost always miss is that sum must be reset to zero at every new row, inside the outer loop: if you declare it outside both loops, you get a cumulative sum over the whole matrix instead of a sum per row.
Exercise 2 — array and function: finding the position of the maximum.
Write a function that receives an array of integers and its length, and returns the index of the maximum element.
#include <stdio.h>
int index_of_max(int arr[], int length) {
int index = 0;
for (int i = 1; i < length; i++) {
if (arr[i] > arr[index]) {
index = i;
}
}
return index;
}
int main(void) {
int grades[5] = {6, 8, 5, 9, 7};
int i_max = index_of_max(grades, 5);
printf("The maximum is %d, at position %d\n", grades[i_max], i_max);
return 0;
}
Two choices to note, because they are the kind of questions the written theory paper asks: the loop starts from i = 1, not from 0, because position 0 is already the starting candidate (index = 0, so comparing it with itself would be pointless); and the function returns the index, not the maximum value, because that way the caller also gets the position information, not just the number. With grades = {6, 8, 5, 9, 7} the maximum is 9, at position 3.
Exercise 3 — recursion: the factorial with the correct base case.
#include <stdio.h>
long factorial(int n) {
if (n == 0) {
return 1;
}
return n * factorial(n - 1);
}
int main(void) {
for (int n = 0; n <= 5; n++) {
printf("%d! = %ld\n", n, factorial(n));
}
return 0;
}
The base case is n == 0, which returns 1 without making any further calls. Each subsequent call reduces n by one and relies on the result of the smaller call: factorial(3) calls factorial(2), which calls factorial(1), which calls factorial(0), which finally returns 1 without calling anyone — at that point the calls “unwind” backwards, multiplying: 1, then 1×1=1, then 2×1=2, then 3×2=6. If the base case were written as n == 1 instead of n == 0, the call factorial(0) would never meet that condition and the program would keep decrementing n without stopping.
To train on logic, loops and data structures before the exam, at /simulazioni/ you will find tests organised by subject and topic: for computer science we don’t yet have a practice test dedicated to loops and arrays, and I tell you so openly instead of linking you to something unrelated. In the meantime the best practice remains writing and running these exercises at the PC, exactly as in the exam.
How we work in lessons
With those who arrive stuck on nested loops or arrays, the first job is not “explaining the syntax better”: it is getting you to draw the data structure on paper before writing code, and to run the program by hand, line by line, before launching it on the PC. It is the same method I use with those tackling pointers in C later in the course — there the mental model matters even more, because nobody protects you from index errors any more. If you also want to practise on your own with a more permissive syntax before going back to the rigour of C, the 6-week Python roadmap covers loops, lists and functions with the same kind of logic.
The computer science lessons are online and one to one: we start from where you got stuck — often precisely a nested loop or a function that doesn’t do what you thought — and build from there. We start with a free 30-minute introductory call; for the single lesson and the 10-hour package see the up-to-date prices on the pricing page. Payment is always offline — bank transfer, Satispay, PayPal, card, Apple Pay or Revolut.
When loops and arrays work, the next step is functions: I have explained passing by value and by reference. If you are starting from zero with algorithms, the foundation is in the Year 2 spreadsheet article.
If you want to talk before booking, we are at /contatti/.