Bank 1 — Mindset and compilation¶
Eleven exercises on how a C++ program becomes a running process, and on the difference between a thing and a bag of fields. Module 1. Levels L1–L6.
Solutions are in Solutions and answers; nudges are in Hints. Attempt first.
Exercises¶
E01 — Where does each mistake fail? L1 concept¶
C++ builds a program in three stages: preprocessing, compilation and linking. For each of the four mistakes below, say which stage reports it, and what the message is about.
- A missing semicolon.
- A missing
#include <iostream>used only forstd::cout. - A function that is declared and called but never defined.
- A statement that dereferences a null pointer at run time.
Task. One sentence per mistake. For (4), name the stage and then say why no compiler stage could have caught it.
E02 — Value or reference? L2 predict¶
Write the exact output before running it.
#include <iostream>
void bumpByValue(int n) { n = n + 1; }
void bumpByRef(int& n) { n = n + 1; }
int main() {
int a = 10;
bumpByValue(a);
std::cout << a << '\n';
bumpByRef(a);
std::cout << a << '\n';
}
Task. Two lines of output, and a one-sentence explanation of the difference.
(Why can the two functions not both be named bump and called with a?)
E03 — Fill in the totals L2 complete¶
The program below prints the total of an array of prices and the total after a 10% discount. Two lines are missing.
#include <iostream>
double total(const double* prices, int count) {
double sum = 0.0;
for (int i = 0; i < count; ++i) {
sum += prices[i];
}
return sum;
}
int main() {
const int n = 5;
double prices[n] = { 4.50, 12.00, 3.25, 8.00, 1.75 };
double before = total(prices, n);
// TODO (1): compute `after` as 90% of `before`
std::cout << "before: " << before << '\n';
// TODO (2): print the line "after: <value>"
}
Task. Supply the two missing statements so the program prints the total before and after the discount. State what the two totals are.
E04 — The marks report L2 trace scenario¶
A classroom tool prints the average mark of a class. Work out the output by hand, line by line.
#include <iostream>
int main() {
int marks[5] = { 62, 75, 81, 48, 90 };
int sum = 0;
for (int i = 0; i < 5; ++i) {
sum += marks[i];
}
double average = sum / 5;
std::cout << "sum: " << sum << '\n';
std::cout << "average: " << average << '\n';
return 0;
}
Task. Give the two printed lines, then say whether the average is what a teacher would expect for a 5-mark class averaging 71.2, and why.
E05 — It will not build L2 debug scenario¶
A student's first program for a "course roster" tool does not compile.
#include <string>
int main() {
std::string name = "Ayesha";
std::cout << "Roster entry: " << name << '\n';
return 0;
}
Task. State the cause, then fix it in the smallest way that still leaves the program readable. Do not guess the compiler message — reproduce it with your own toolchain and read it.
E06 — Add a column, count the cost L3 modify scenario¶
An inventory report stores each product as three parallel arrays:
#include <iostream>
#include <string>
int main() {
std::string names[3] = { "Nails", "Screws", "Bolts" };
int stock[3] = { 500, 1200, 300 };
double price[3] = { 0.02, 0.05, 0.08 };
for (int i = 0; i < 3; ++i) {
std::cout << names[i] << ": " << stock[i]
<< " at " << price[i] << '\n';
}
return 0;
}
Task. Add a fourth column, supplier (a std::string), with one supplier per
product, and print it. Then write down how many lines you changed and why a
fourth parallel array is a warning sign rather than just a small edit.
E07 — Integer arithmetic L2 predict¶
#include <iostream>
int main() {
int a = 7;
int b = 2;
double c = 7 / 2;
double d = 7.0 / 2;
std::cout << c << '\n';
std::cout << d << '\n';
std::cout << a / b << '\n';
return 0;
}
Task. Three lines, exactly as printed. Explain, in one sentence, why c and d
differ even though both are double.
E08 — Where can this be corrupted? L4 analyze¶
Read the procedural catalogue below. List every way a later programmer could make it report the wrong thing without the compiler objecting.
#include <iostream>
#include <string>
std::string titles[4] = { "Dune", "Emma", "Ilium", "Neuromancer" };
bool onLoan[4] = { false, false, false, false };
int borrowedCount = 0;
bool lend(int index) {
if (index < 0 || index >= 4) return false;
if (onLoan[index]) return false;
onLoan[index] = true;
borrowedCount++;
return true;
}
int main() {
lend(1);
lend(3);
std::cout << "borrowed: " << borrowedCount << '\n';
return 0;
}
Task. At least four distinct fragilities, each naming the specific line or identifier involved, and for each one: would anything in this program detect it?
E09 — Off by one L3 debug¶
A scoreboard is supposed to add up the points of all five rounds, but it reports a total that is a few points short.
#include <iostream>
int main() {
int points[5] = { 10, 20, 30, 40, 50 };
int total = 0;
for (int i = 1; i < 5; ++i) {
total += points[i];
}
std::cout << "total: " << total << '\n';
return 0;
}
Task. (a) Work out the wrong total it prints. (b) State the defect in one sentence. (c) Fix it, and give the correct total.
E10 — Model a club L5 design scenario¶
A student club tracks members, events and attendance. Members sign up for events; after each event the club records who attended.
Task. On paper (no syntax), for each candidate type write:
- its responsibility, in one sentence with no "and";
- the data it holds;
- the operations it offers.
Then name one thing you deliberately did not make a type, and say why.
How you will be judged. On the exclusions as much as the inclusions. A design in which everything becomes a type has made no decisions.
E11 — Before you reach for classes L6 refactor scenario¶
The club treasurer keeps attendance in a growing program built from the arrays in E06's style. A new requirement arrives: "each member can attend many events, and we want to ask how many events a given member attended."
Task. In one page, before writing any code:
- State what the four or five parallel arrays would need to become, and why the current shape fights the new question.
- Propose the types you would introduce, with their responsibilities in one line each.
- Name one risk of your refactor — something that could break that currently works.
- Argue the other side: give one reason to keep the arrays and add a fifth function instead, then say why you rejected it (or accepted it).
Success. A reader can see both designs and your reason for the one you chose. There is no single correct answer; there is a defended one.
Next topic: Classes and encapsulation · Hints: hints.md · Solutions: solutions.md