CS U111 · Blocks B–C · Notes: the compressed map

Operators, I/O and selection, in one page

The rules behind every "what does this print?" question on operators, scanf, if, ?: and switch, plus the rewrite templates and the traps. This is the revision layer: first time with this material? Start with the lesson, which has a stepper for short-circuit evaluation.

Start here: what the past papers say

This is Blocks B–C of the syllabus (lectures 4–9, Hanly & Koffman ch. 2 and ch. 4). It's the material from Labs 1–3 that felt easy at the time. The three past mid-sem papers (the predecessor course, CS F111; all in past papers) come back to it as trick questions again and again. By my tagging of each question:

PaperQuestions on this page's topics≈ marks of 90
2024-25 Sem 1Part 1: Q1, Q2, Q3, Q5, Q7, Q12, Q14, Q15 · Part 2: the whole rewrite section (Q1–Q5) and Q643
2025-26 Sem 1Q1 (b, e, g), Q2 (b, d, h, i, j), Q4 (a, c, d, e, f)31
2025-26 Sem 2Part A: Q3, Q5, Q6, Q9, Q10 · Part B: Q2 (a, b); Q5 (16) is built around a switch21 + Q5

And a grounding fact: school never teaches any of this. The comma operator, short-circuit side effects, switch fall-through and scanf field widths are new to the whole batch, JEE or not. It's a closed set of about fifteen rules, and they're all below. One caveat: these papers are from the old course code. The CS U111 paper's date and format come from the Institute calendar (last year's mid-sem was 9 Oct).

The rules, one card each

1 · Integer division chops; equal ranks go left to right

"what does 2*3/4 - 3/4*2 print?"

7 / 2         // 3   (towards zero; -7/2 is -3)
2*3/4 - 3/4*2 // 6/4 - 0*2 = 1 - 0 = 1

Do * / % strictly left to right. 3/4 is already 0 before the *2.

2 · One double operand makes the operation real; a cast converts one value

averages · "the result should be a double" · (int)(…) questions

(double) sum / n     // real division: 7/2 → 3.5
(double) (sum / n)   // too late: 3.0
int x = 2.5;         // stores 2 (clang: "changes value from 2.5 to 2")

3 · % keeps the sign of the left operand

"negative even values" · odd/even tests

-7 % 2    // -1   so  x % 2 == 1  is FALSE for negative odd x
x % 2 != 0   // the safe "odd" test;  x % 2 == 0  is fine for evens

4 · Comparisons give 1 or 0; nonzero means true; ! is rank 1

!x < 5 · a < b < c · "which has higher precedence than %?"

!x < 5      // (!x) < 5: always 1, since !x is 0 or 1
3 < 2 < 1   // (3<2) < 1 = 0 < 1 = 1   (Apple clang 21 refuses to compile it)

Ladder, strongest first: unary ! ++ -- (type) sizeof › * / % › + - › << >> › < <= > >= › == != › & › && › || › ?: › = += › ,

5 · && and || short-circuit: a skipped side is never run

any ++/--/assignment on the right of && or ||

a || --b     // a nonzero → --b skipped, b unchanged
a && ++j     // a zero    → ++j skipped
!i && ++j || ++k    // means (!i && ++j) || ++k

6 · Single & is bitwise: both sides always run, and "true & true" can be 0

if ((y>=0) & (x=x+1)) · bit counting

1 & 4   // 0: 001 and 100 share no bits  (but 1 && 4 is 1)
6 & 3   // 2: 110 and 011 share the 2s bit
if (n & i) count++;  i = i << 1;   // counts 1-bits; 2273 → 5

The 2025 answer key read & as && twice: Q2b is 16 (key 14) and Q2h is 012348 (key 348). See Worked example 3.

7 · Postfix gives the old value, prefix the new; never change one variable twice

while (i++) · a-- && … · c = (a>=7) ? a++ : ++a

do { … } while (i++);   // tests the OLD i: 0 stops the loop, then i is 1
i = i++ + ++i;          // undefined behaviour (clang: "multiple unsequenced modifications to 'i'")

8 · Comma operator: evaluate all, keep the last

b = (a+1, c+1, 100, a+c)

int b = (a+1, c+1, 100, a+c);   // b = a + c

It's the weakest operator of all, so it needs the brackets. Without them the commas mean something else.

9 · = inside a condition assigns, and the value is what was stored

if (x = 0) · (x = x + 1) inside a test

if (x = 0) …   // x becomes 0; condition is 0 → always false

10 · Characters are numbers: '0'…'9' = 48…57, 'a'…'z' = 97…122, Enter = 10

"sum of the digits in a character stream" · "highest letter"

sum += c - '0';                 // '7' - '0' = 7
if (c >= '0' && c <= '9') …     // same as c >= 48 && c <= 57, but readable
while (c != '\n') …             // '\n' is 10

11 · An else belongs to the nearest unmatched if

"for which inputs does it print s2?" · unbraced nested ifs

if (a > b) if (b > c) s1; else s2;   // else pairs with (b > c)

Read the path to the target: s2 needs a > b and "not b > c", i.e. b <= c, equality included. The lesson has the decision-tree figure.

12 · c ? X : Y evaluates only the chosen branch; chains read like else-if

"rewrite using the conditional operator" · printf inside ?:

g = (s>=90)?'A' : (s>=80)?'B' : (s>=70)?'C' : (s>=60)?'D' : 'F';
(a==1) ? printf("One") : (a==2) ? printf("Two") : printf("Other");

13 · switch: jump to the matching label (else default, wherever it is), then fall through to break

missing breaks · default written first · "why does it print PositiveZero?"

switch (i) { case 2: i*=i; case 4: i*=i; default: i*=i; break; case 16: … }
// i = 2 → 4 → 16 → 256, stop at break.   i = 1 → default only → 1

14 · scanf matches its format like a pattern and stops at the first mismatch

field widths · literal characters · %c · type letters

%2d, %5f   // read AT MOST 2 / 5 characters (the '.' counts)
"%d-%d"    // the '-' must be typed exactly; "10 20" gives n=10, m untouched
" %c"      // %c takes the very next char, even a space; the leading space skips whitespace
%d int · %f float · %lf double · %Lf long double · %c char · %u unsigned

15 · printf returns the number of characters printed

"make if/else print HelloWorld" · printf inside conditions

if (!printf("Hello")) …   // prints Hello, value 5, !5 = 0 → the else runs
printf("%5.2f", 3.14159); // " 3.14"  (width 5, 2 decimals)   %.1f of 2.75 → 2.8

The rewrite templates

Whole sections of two papers were "rewrite this using…". Each has a fixed template:

From → toTemplateWhere marks go
switch → nested if-else, no else ifif (v==1) {…} else { if (v==2) {…} else { if (v==3) {…} else {default} } }Each else opens braces; the default is the innermost else
if-ladder ↔ ?: chainx = c1 ? v1 : c2 ? v2 : … : vElse;Same order of tests; the last value has no condition
ternary → if-else ladderd = m ? (s>100 ? .2 : .1) : 0; becomes if (m && s>100) d=.2; else if (m) d=.1; else d=0;Every path of the nested ?: becomes one rung
for → do-whileinit; do { body; update; } while (cond);Nested: the inner init goes inside the outer body. State the zero-trip assumption

Three worked examples at exam level

Worked example 1 · 2024 P1 Q1 (2 marks, −25% if wrong)

Short-circuit with side effects

int a = 1, b = 1;
int c = a || --b;
int d = a-- && --b;
printf("a = %d, b = %d, c = %d, d = %d", a, b, c, d);
  1. Write the variables in a row before reading any code: a=1 b=1 c=? d=?.
  2. Line 2. Left of || is a = 1, true. || is decided, so --b is skipped: b stays 1, and c = 1.
  3. Line 3, left side. a-- hands over the old value 1 (true), then a becomes 0.
  4. Line 3, right side. && with a true left side must evaluate the right: --b makes b 0, value 0. So d = 1 && 0 = 0.
  5. Read off: a = 0, b = 0, c = 1, d = 0, which is option (b). (Option (a), b = 1, is the answer for students who forget that --b does run in line 3.)

Worked example 2 · 2024 P1 Q2 and Q15 (5 marks)

Parsing input with a scanf pattern

scanf("%2d %5f %2d", &n, &x, &m); with input 1234.5678 99.88 777, then printf("n= %d,x=%5.2f,m = %d", n, x, m);

  1. Put a cursor at the start of the input and move it piece by piece through the format.
  2. %2d: at most 2 characters → 12. n = 12. Cursor now before 34.5678….
  3. The space in the format skips whitespace; there's none here. %5f: at most 5 characters → 34.56. x = 34.56. Cursor before 78 99.88….
  4. %2d → 78. m = 78. The rest of the line is never read.
  5. Format the output: %5.2f of 34.56 is exactly 34.56 (5 characters). Printed: n= 12,x=34.56,m = 78, which is option (b).
  6. Q15, same method: scanf("%d-%d") with input 10 20. %d reads 10. The format then needs a literal - but the input has a space, so scanf stops. m keeps its initial 0 and the output is 10-0, option (c).

Both verified by compiling and piping in the exact input line. For Q15 scanf also returns 1 (one item read), which is how a real program would detect the mismatch.

Worked example 3 · 2025 Q2h (2 marks), where the official key is wrong

A printf on the right of a single &

int i, j, count;
i = 0; count = 0;
for (j = -2; j <= 2; j++) {
    if ((j >= 1) & (printf("%d", i)))
        count += j;
    i++;
}
count += i;
printf("%d", count);
  1. Spot the operator. It's &, not &&, so the printf runs on every pass, whatever j is. Also note there are no braces: only count += j is inside the if, and i++ runs every pass.
  2. Trace it, one row per pass. printf("%d", i) prints one digit, so it returns 1.
    jprints(j>=1) & 1counti after
    -200 & 1 = 001
    -11002
    02003
    131 & 1 = 114
    24135
  3. After the loop: count += i → 3 + 5 = 8, printed straight after the digits.
  4. Answer: 012348. The key's 348 is what && would print, since it would skip the printf while j < 1. Compiled with clang, the program prints 012348.
Check yourself: the same paper's Q2b has if ((y>=0) & (x=x+1)) z = z + x; for y from −3 to 3, then z = z + y. The key says 14. What's right?

x goes up on every pass: 1, 2, …, 7. The condition is (y>=0) & x, which is 1 only when y >= 0 and x is odd (bitwise with 1). That happens at y = 1 (x = 5) and y = 3 (x = 7), so z = 12. After the loop y = 4, so z = 16. The key's 14 is the && answer.

Classic traps: the standard ways marks are lost

The mistakeWhat happensThe fix
Reading & as &&You skip a side effect that really happens, or treat 1 & 4 as true. It cost the 2025 key two answersCircle every single & before tracing
Running the skipped side of &&/||A ++ that never happened gets countedDecide the left side first; ask "is it already decided?"
Integer division too early3/4*2 = 0; an average truncatedLeft to right; cast before dividing
x % 2 == 1 as the odd testFails for negative odd numbersx % 2 != 0
Forgetting fall-throughYou stop at the first matching caseRun downwards until break or }
Treating default position as meaningfulYou run default because it's written firstdefault only runs when nothing matches
scanf width ignoredYou read 1234 into a %2dWidth = maximum characters; move a cursor through the input
Literal in the format ("%d-%d")You assume the second value is readA mismatch stops scanf; the later variables keep their old values
Wrong type letter (%f for double in scanf, %lf for long double)Garbage values; clang warns format specifies type 'double *' but the argument has type 'long double *'%f float · %lf double · %Lf long double
Dangling else trusted to indentationWrong branch; clang: add explicit braces to avoid dangling elsePair with the nearest unmatched if; in your own code, always brace
= for ==The condition is the assigned valueclang warns using the result of an assignment as a condition without parentheses
Missing a char declaration in a "write the declarations" questionLost marks (the 2025 Q4d key itself omits char grade = 'B';)Tick off every variable the spec names
|| where && is needed in a two-array loopReads past the shorter array (2024 P2 Q8 accepted both, but only && is safe)"Both still have data" is &&

Minimal prerequisite kit

The complete list of school-level facts this page leans on:

FactWhere it appears
Quotient and remainder (17 = 5 × 3 + 2)/ and %; digit tricks; odd/even
AND/OR truth tables (sets, logic)&&, || and when they are decided early
Writing a small number in binary via powers of 2&, <<, bit counting; also the number-systems drill
Rounding to a given number of decimals%5.2f, %.1f
Characters have an order (a < b < … < z)ASCII arithmetic; "highest letter"
Unpack this step: why & with 1 tests "odd"

An odd number's binary form ends in 1, and 1 is …0001. Bitwise AND with 1 keeps only that last bit: 5 & 1 = 1, 6 & 1 = 0. That's why the 2025 Q2b condition was true only for odd x.

What to practise

Ranked for the days before the mid-sem. The past-paper questions come first, because they're the exam's own style.

SkillPast-paper questionsDrill / textbookHow many
Short-circuit, ++/--, precedence24 P1 Q1 · 25 Q2d · 26 A Q3Operators drill · Hanly ch. 4 "Conditions"3 + 1 sheet
Division, casts, mixed types24 P1 Q5 · 25 Q4c · 26 A Q5Hanly ch. 2 "Arithmetic Expressions"3
Single &, bits25 Q2b, Q2h · 26 A Q10Operators drill (not in Hanly ch. 2/4)3
Comma, ?: chains24 P1 Q3 · Q14 · 26 A Q6 · 25 Q1gOperators drill (lecture material)4
switch fall-through, default24 P1 Q7 · 25 Q2i · 26 B Q2bHanly ch. 4 "The switch Statement"3
Nested if / conditions24 P1 Q12 · 25 Q4e, Q4f · 26 B Q2aHanly ch. 4 "Nested if Statements and Multiple-Alternative Decisions"4
scanf/printf formats24 P1 Q2 · Q15 · 24 P2 Q6 · 25 Q1b · 26 A Q9Hanly ch. 2 "Formatting Numbers in Program Output"5
Rewrites between constructs24 P2 Q1–Q5 · 25 Q4aWrite them on paper, then compile to check6

Hanly references are section titles rather than numbers, because editions renumber. The comma operator, bitwise & and much of ?: aren't in ch. 2/4 at all: they come from lectures and the past papers.

Don't do this

Don't memorise C's full precedence table (all 15 levels) or go hunting through "C puzzle" books. The papers use exactly the ladder in card 4, and the puzzle books are full of undefined-behaviour tricks (i++ + ++i) that no sensible examiner can mark. The past papers plus a daily drill sheet are the whole preparation.