Topic Revision Tests — T1 to T4

12 questions each · ~20 min each · these span units — take them after finishing the whole topic cluster, not mid-unit · attempt ALL before any key · Hub · T5–T8 →


T1 — Variables, types & expressions (Units 02–03)

Q1. [Easy] Which type for a single letter grade?

Q2. [Easy] int x = 2.9; stores…

Q3. [Easy] Which is not a valid identifier?

Q4. [Medium] What does this print?

int a = 9, b = 4;
cout << a / b << " " << a % b;

Q5. [Medium] What does this print?

double d = 7.0 / 2;
int i = 7 / 2;
cout << d << " " << i;

Q6. [Medium] Which expression converts Celsius c (a double) to Fahrenheit correctly?

Q7. [Medium] What is b after int a = 5; int b = a++ + 2;?

Q8. [Medium] What does this print?

int x = 10;
x -= 3;
x *= 2;
cout << x;

Q9. [Hard] What does this print?

int total = 2500;
cout << total / 1000 << "k " << (total % 1000) / 100 << "h";

Q10. [Hard] A student writes double avg = (a + b + c) / 3; with three ints and gets whole numbers only. The minimal correct fix is…

Q11. [Hard] What does this print?

bool flag = true;
flag = !flag;
flag = flag && false;
cout << boolalpha << flag;

Q12. [Hard] const double TAX = 0.15; appears at the top of the file and is used in four functions. The main benefit versus writing 0.15 inline four times is…

T1 — Answer key

Q1 — b. A grade letter is one character. string would also work for multi-character grades, but for a single letter, char is the honest type.

Q2 — b. Initializing an int from a double truncates toward zero: 2.9 →

  1. Compilers warn (-Wall) — another reason warnings are always on.

Q3 — c. Identifiers cannot start with a digit. Leading underscores and embedded digits are fine.

Q4 — b. Integer division 9/4 = 2; remainder 9%4 = 1. The pair partitions 9 = 2·4 + 1.

Q5 — a. 7.0 / 2 promotes to 3.5 — but that promotion belongs to that one expression only. 7 / 2 on ints is 3. Each expression is evaluated with its own types.

Q6 — b. The famous 9/5 trap: with int literals, 9 / 5 is 1, and both (c) and (d) compute c + 32. Floating literals force real division.

Q7 — a. Post-increment: the old value (5) participates in the expression, then a becomes 6. b = 5 + 2 = 8.

Q8 — a. 10 − 3 = 7; 7 × 2 = 14. Compound operators read left to right as sequential updates.

Q9 — a. 2500/1000 = 2 (integer division), remainder 500, 500/100 = 5. Unit decomposition with / and % — the pattern from hundreds and seconds.

Q10 — a. One 3.0 promotes the entire division. (d) casts after the integer division already destroyed the fraction; (b) never divides.

Q11 — b. true → !true = false → false && anything = false. boolalpha prints the words; without it you’d see 0.

Q12 — b. The named constant documents meaning, centralizes change, and gets compiler enforcement. Executable speed is identical — the win is maintainability and safety.


T2 — Control flow: selection & iteration (Units 04–06)

Q1. [Easy] Which if correctly rejects negatives and values above 100?

Q2. [Easy] How many times does the body of for (int i = 3; i > 0; i--) run?

Q3. [Easy] switch cases need which type of expression?

Q4. [Medium] What does this print for input 12?

int n; cin >> n;
if (n % 3 == 0 && n % 4 == 0) cout << "both";
else if (n % 3 == 0)          cout << "three";
else if (n % 4 == 0)          cout << "four";
else                          cout << "neither";

Q5. [Medium] What is s after this?

int s = 0;
for (int i = 1; i <= 10; i++) {
    if (i % 2 != 0) continue;
    s += i;
}

Q6. [Medium] What does this print?

int n = 100;
while (n > 0) {
    n -= 30;
}
cout << n;

Q7. [Medium] Which loop prints 5 4 3 2 1?

Q8. [Medium] What does this print?

int i = 0;
while (i < 10) {
    if (i == 3) break;
    cout << i;
    i++;
}

Q9. [Hard] What does this print?

for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
        if (j == i) continue;
        if (j > i) break;
        cout << i << j << " ";
    }
}

Q10. [Hard] A grading ladder must output A (90+), B (80–89), C (70–79), F otherwise. Which ladder is correct for input 85?

Q11. [Hard] What does this print?

int count = 0;
for (int i = 100; i <= 999; i += 100)
    for (int j = 0; j < 3; j++)
        if ((i + j) % 2 == 0) count++;
cout << count;

Q12. [Hard] The sentinel loop while (cin >> x && x != -1) { sum += x; } is preferred over do { cin >> x; if (x == -1) break; sum += x; } while (true); mainly because…

T2 — Answer key

Q1 — a. A value is either below 0 or above 100 — the union needs ||. (b) is impossible (both at once), (c) is the chained-comparison trap, (d) inverts the logic twice.

Q2 — b. i = 3, 2, 1 — the body runs before the decrement ends the loop.

Q3 — b. Cases are integers, chars, or enums — values with exact equality. Ranges and strings need if-ladders.

Q4 — c. 12 % 3 = 0 and 12 % 4 = 0 → both. The first matching branch wins; ordering “both” first matters.

Q5 — b. continue skips odds; evens sum to 30. Trace: 2, 6, 12, 20, 30.

Q6 — c. Trace fully: 100→70→40→10→−20. The condition n > 0 is still true at 10, so the body runs once more and overshoots zero before the loop stops. Loops terminate on the condition, not on the target — a trace table is the only honest way to answer this class of question.

Q7 — d. Both (a) and (c) produce 5 4 3 2 1 — (c) by arithmetic reflection. Counting down and counting up-with-math are equivalent forms; choose the one that reads better.

Q8 — a. i = 0, 1, 2 print; i = 3 breaks before printing. Break fires before the body’s output — placement decides.

Q9 — a. i=1: j=1 continue (skip), j=2 >1 break → nothing. i=2: j=1 prints 21, j=2 continue, j=3 break. i=3: j=1 31, j=2 32, j=3 continue. Total: 21 31 32 . The jumps act per-inner-iteration — the classic nested-loop trace.

Q10 — b. The else-if ladder gives each band an implicit range (85 ≥ 80 → B). Option (a)’s independent ifs fall through to C as well — 85 would print B and C. Ascending thresholds with else-if is the idiom.

Q11 — c. i takes 100, 200, 300; j takes 0, 1, 2. Even sums: 100+0, 100+2, 200+0, 200+2 → count 4. (The option text’s own trace was the hint — (b) miscounts by stopping early.)

Q12 — b. The one-line condition documents “readable stream, not the sentinel” — the loop’s complete contract. The do-while version scatters the stop logic and risks summing the sentinel if the break is misplaced.


T3 — Functions & decomposition (Units 07–08)

Q1. [Easy] Which line calls the function int roll() correctly?

Q2. [Easy] A prototype (declaration) differs from a definition because it…

Q3. [Easy] Which parameter can change the caller’s variable?

Q4. [Medium] What does this print?

int f(int x) { return x * 2; }
int main() {
    cout << f(f(3));
}

Q5. [Medium] What does this print?

void paint(char c, int n = 3) {
    for (int i = 0; i < n; i++) cout << c;
}
int main() {
    paint('*');
    cout << "|";
    paint('#', 5);
}

Q6. [Medium] What does this print?

double half(double x) { return x / 2; }
int half(int x)       { return x / 2; }
int main() {
    cout << half(5) << " " << half(5.0);
}

Q7. [Medium] What does this print?

void stats(int a, int b, int& lo, int& hi) {
    lo = (a < b) ? a : b;
    hi = (a > b) ? a : b;
}
int main() {
    int p = 0, q = 0;
    stats(9, 4, p, q);
    cout << p << q;
}

Q8. [Medium] A function’s purpose, parameters, and return are documented before its body. This practice chiefly helps…

Q9. [Hard] What does this print?

int mystery(int& a, int b) {
    a = a + b;
    return a - b;
}
int main() {
    int x = 10, y = 3;
    int r = mystery(x, y);
    cout << x << " " << r;
}

Q10. [Hard] What does this print?

bool isVowel(char c) {
    c = tolower(c);
    return c=='a'||c=='e'||c=='i'||c=='o'||c=='u';
}
int main() {
    cout << isVowel('E') << isVowel('x');
}

(with <cctype> included; no boolalpha)

Q11. [Hard] A driver program exists to…

Q12. [Hard] Refactoring main that mixes input, calculation, and printing into functions should…

T3 — Answer key

Q1 — b. A call is the name with parentheses; assigning its result needs a matching type.

Q2 — a. Declaration = signature + semicolon; definition adds the body. Headers carry declarations, source files carry definitions.

Q3 — b. Only a non-const reference aliases the caller’s object. Value parameters mutate copies; const forbids writing.

Q4 — b. Inner first: f(3) = 6; outer: f(6) = 12. Nesting reads inside-out.

Q5 — a. One argument → default n = 3 → ***; two arguments override → #####. Defaults fill the right end of the list.

Q6 — a. The literal 5 is int → int version → 2; 5.0 is double → double version → 2.5. Overload resolution matches types first.

Q7 — b. Out-params: p (lo) = 4, q (hi) = 9 → printed 49. The order of the output variables in the call decides — argument positions, not names.

Q8 — b. The signature-with-meaning is the interface contract. Users (including future you) code against it without reopening the body.

Q9 — b. The reference parameter updated x to 13; the return value is 13 − 3 = 10. One function, two channels: mutation + return. Use deliberately, not accidentally.

Q10 — a. isVowel(‘E’) → tolower → ‘e’ → true → prints 1; ‘x’ → 0. So 10. Option (b) second-guesses itself into nonsense — a reminder to verify options, not just trust their commentary.

Q11 — a. A driver is a small main whose only job is exercising one function: known inputs in, expected outputs checked. The unit-testing habit in miniature.

Q12 — a. Behavior-preserving is the definition of a refactor. Mixing in behavior changes (b) makes every later bug ambiguous: restructure or edit? One axis at a time.


T4 — Collections: arrays & vectors (Unit 09)

Q1. [Easy] Which accesses the last element of vector<int> v (non-empty)?

Q2. [Easy] int a[10] = {0}; …

Q3. [Easy] Which adds 7 to the end of vector<int> v?

Q4. [Medium] What does this print?

int a[4] = {2, 4, 6, 8};
int s = 0;
for (int i = 0; i < 4; i += 2) s += a[i];
cout << s;

Q5. [Medium] What does this print?

vector<int> v = {5, 1, 9, 3};
int best = 0;
for (size_t i = 1; i < v.size(); i++)
    if (v[i] > v[best]) best = i;
cout << v[best];

Q6. [Medium] What does this print?

int a[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5 / 2; i++) {
    int t = a[i]; a[i] = a[4 - i]; a[4 - i] = t;
}
for (int i = 0; i < 5; i++) cout << a[i];

Q7. [Medium] Which range-based loop modifies every element (doubling)?

Q8. [Medium] What does this print?

vector<int> v;
for (int i = 1; i <= 3; i++) v.push_back(i * i);
cout << v.size() << ":" << v[2];

Q9. [Hard] What does this print?

int a[6] = {4, 1, 4, 1, 4, 9};
int target = 4, count = 0;
for (int i = 0; i < 6; i++)
    if (a[i] == target) count++;
cout << count;

Q10. [Hard] What does this print?

vector<int> v = {7, 3, 5};
v.insert(v.begin(), 1);
v.erase(v.begin() + 1);
for (int x : v) cout << x;

Q11. [Hard] Parallel arrays (string names[50]; int marks[50];) are replaced by one struct Student { string name; int marks; }; array chiefly because…

Q12. [Hard] What does this print?

vector<int> v = {2, 4, 6, 7};
for (size_t i = 0; i < v.size(); i++) {
    if (v[i] % 2 == 0) v.erase(v.begin() + i);
}
for (int x : v) cout << x;
T4 — Answer key

Q1 — b. Last valid index is size−1. v[size()] is one past the end; negative indices do not exist in C++.

Q2 — b. The = {0} initializer zero-fills the entire array. Uninitialized arrays hold garbage — always initialize before reading.

Q3 — b. push_back appends and grows. v[7] = 0 would write index 7 — past the end if size < 8, a different operation entirely.

Q4 — b. i takes 0, 2 → 2 + 6 = 8. Step-2 traversal skips odd indices.

Q5 — b. The index-of-max pattern: best ends at index 2 (value 9). Storing the index keeps position information — the trick the labs reuse for “which row?” answers.

Q6 — a. Swap ends inward: (1,5), (2,4) → 54321. i < 5/2 = i < 2 — two swaps, middle element untouched.

Q7 — b. The & binds a reference: writes hit the element. (a) modifies a copy, (c) is read-only by law, (d) confuses iterators with values.

Q8 — a. Pushed 1, 4, 9 → size 3, index 2 is 9. Squares built by loop — the collection grows with the data.

Q9 — b. 4 appears at indices 0, 2, 4 → 3. Linear counting is O(n) and works on any order — no sortedness required.

Q10 — b. Insert 1 at the front → {1,7,3,5}. Erase index 1 — which now holds the 7, not the 3 — → {1,3,5} → 135. The lesson: after an insert or erase, every later index means something different; re-derive positions from the new state, never from the old.

Q11 — b. Any reordering must be replicated by hand across every parallel array — the classic silent misalignment. The struct makes one swap move name+marks together: cohesion enforced by the type.

Q12 — b. Trace the shifts: i=0 erases 2 → {4,6,7}; i=1 examines v[1] — now 6, because 4 slid into slot 0 — erases 6 → {4,7}; i=2 is past size 2, loop ends. The 4 was never examined: erasing shifts every later element left while i marches forward, so the element that moves into the current slot escapes the test. Fixes: iterate backward, or rebuild into a new vector. Output 47.


Next: T5–T8 — Strings, Files, Memory, OOP → · Hub