Conditionals in C — exercises with grades, triangles, a login without loops and bus fares (and the 1.10 € balance that was not 1.10 €)
To practise conditionals I built a simulator of my bus card: you loaded a balance, picked a trip and it told you whether you had enough. I wanted a special message for when the balance was exactly the ticket price, 1.10 €. I tried it with 1.10 € on the card and the program told me it did not match. A number that is not equal to itself. I spent half an afternoon convinced gcc was broken, until I printed the balance with ten decimals. That program is snippet 3 in “What’s wrong here?”, and the lesson it left (you do not compare a float with ==) comes back in the solutions.
You have seen the C conditionals theory and written the three programs in the practice. Now it is your turn: four exercises on three levels, three snippets with a hidden bug, solutions commented line by line and a cheat sheet to revise before the exam. Every program reads with scanf and every output you will see comes from a real run, with what was typed after each question.
Table of Contents
How to use this article
- Read the statement and the expected output. Write your solution in gedit without looking at the solution.
- Compile with
gcc -Wall -Wextra exercise.c -o exerciseand do not move on until there are no warnings. - Run it with the same data as the statement and compare your output line by line. If you are stuck for more than 10 minutes, open the hint.
- Compare with the commented solution: even if your program works, read the “Why it is done this way”.
Basic level
Exercise 1: grade converter between systems
Write a program that asks for a grade on the Spanish scale (0-10) and converts it to the US letter grade and to the 0 to 100 scale. If the grade is out of range or not a number, the program complains and ends with return 1. The equivalences are:
| Spanish grade | Letter | 0-100 scale |
|---|---|---|
| 9 to 10 | A | 90 to 100 |
| 7 to 8.9 | B | 70 to 89 |
| 5 to 6.9 | C | 50 to 69 |
| 3 to 4.9 | D | 30 to 49 |
| 0 to 2.9 | F | 0 to 29 |
Expected output with a 7.5:
Spanish grade (0-10): 7.5 --- Conversions --- Spanish scale: 7.50 / 10 US scale: 75.00 / 100 Letter grade: B Status: Pass
An if / else if chain from the highest grade to the lowest for the letter, with braces in every branch. The 0 to 100 scale needs no if: it is a multiplication. And the “Status” fits in a ternary.
Exercise 2: triangle classifier by sides
Write a program that asks for the three sides of a triangle (whole numbers) and classifies it. First check whether the sides form a triangle (each side must be smaller than the sum of the other two); if not, complain and stop. Then classify it:
- By sides: equilateral (all three equal), isosceles (exactly two equal) or scalene (all three different).
- By angles, with Pythagoras and c being the largest side: right-angled if c² = a² + b², obtuse if c² > a² + b² and acute if c² < a² + b².
Expected output with 3, 4 and 5:
Side A: 3 Side B: 4 Side C: 5 --- Classification --- Is it a valid triangle? Yes Type by sides: Scalene Type by angles: Right-angled
Validity is three conditions joined with &&. For Pythagoras you need to know which side is the largest: an if / else if that finds it and, at the same time, adds up the squares of the other two. Use int for the sides so == compares without rounding problems.
Intermediate level
Exercise 3: login system with limited attempts
Simulate a login with three attempts at most, still without loops. The user is “sergio” and, to keep strings out of it (they arrive with pointers), you only ask for the initial (a char) and a PIN (an int). There are three valid PINs, and each one gives a different access level, chosen with a switch:
| PIN | Access level |
|---|---|
| 1234 | Administrator |
| 5678 | User |
| 9999 | Guest |
If an attempt fails, it moves on to the next; if all three fail, the account is locked. Expected output when the third attempt succeeds (typing x and 1234, s and 1111, s and 5678):
=== LOGIN SYSTEM === Attempt 1 of 3 User initial: x PIN: 1234 ✗ Wrong user or PIN Attempt 2 of 3 User initial: s PIN: 1111 ✗ Wrong user or PIN Attempt 3 of 3 User initial: s PIN: 5678 ✓ Access granted. Welcome, sergio. Access level: User
And when all three fail:
=== LOGIN SYSTEM === Attempt 1 of 3 User initial: s PIN: 1 ✗ Wrong user or PIN Attempt 2 of 3 User initial: s PIN: 2 ✗ Wrong user or PIN Attempt 3 of 3 User initial: a PIN: 1234 ✗ Wrong user or PIN Account locked: 3 failed attempts
A variable int logged_in = 0; that becomes 1 when an attempt is correct. Each new attempt goes inside an if (!logged_in). To read the initial, scanf(" %c", &initial): the space before %c is mandatory.
Final challenge
Exercise 4: transport fare calculator
Work out the price of a bus ticket (made-up fares) from the age, the youth card, the zones and the departure hour:
- Base price: 1.50 € for 1 to 3 zones, 2.50 € for 4 to 6 and 3.50 € from 7 on.
- Discount on the base price: under 4, free (100 %); 4 to 12, 50 %; 13 to 25 with a youth card, 30 %; 65 and over, 40 %; everyone else, no discount.
- Rush-hour surcharge (7 to 9 and 17 to 19, both included): +20 % on the already discounted price.
If the zones are below 1 or the hour is not between 0 and 23, the program complains and stops. Expected output for a 22-year-old with a youth card, 4 zones, at 8:
=== BUS FARES === Age: 22 Do you have a youth card? (1 = yes, 0 = no): 1 Number of zones: 4 Departure hour (0-23): 8 --- Breakdown --- Base price (4 zones): 2.50 € Youth card discount: -0.75 € (30 %) Subtotal: 1.75 € Rush-hour surcharge: +0.35 € (20 %) TOTAL: 2.10 €
Split the problem into four steps: base price (if / else if by zones), which discount applies (if / else if by age, storing a kind number), how much it is (a switch on that number) and surcharge (a condition with ||). Careful with the order of the ages: a 10-year-old with a youth card pays as a child.
What’s wrong here?
Three short snippets that compile and run, but do not do what they seem to. Read each one, predict the output and then read the explanation.
Snippet 1: the initial in double quotes
#include <stdio.h>
int main(void) {
char initial = 's'; // as if the user had typed an s
int pin = 1234;
if (initial == "s" && pin == 1234) {
printf("✓ Access granted\n");
} else {
printf("✗ Wrong user or PIN\n");
}
return 0;
}
What do you think it prints, if the initial is an s and the PIN is 1234?
Real output:
✗ Wrong user or PIN
Access denied with the right data. 's' (single quotes) is a char: number 115 in the ASCII table. "s" (double quotes) is a string, and in a comparison C uses the memory address where it is stored. Comparing a small number with a memory address never gives 1. gcc warns twice:
login_quotes.c: In function 'main': login_quotes.c:7: warning: comparison between pointer and integer login_quotes.c:7: warning: comparison with string literal results in unspecified behavior [-Waddress]
Using double quotes for a character. In C, 's' is a char and "s" is a string: they are not interchangeable as in Python.
The fix is to change the quotes, initial == 's', and you get what you expected:
✓ Access granted
If a gcc warning says “comparison between pointer and integer”, it is almost always this: you compared a char with something in double quotes.
Snippet 2: the child with his sister’s youth card
#include <stdio.h>
int main(void) {
int age = 10;
int youth_card = 1; // a child with his sister's youth card
int percent;
if (age <= 25 && youth_card) {
percent = 30;
} else if (age <= 12) {
percent = 50;
} else {
percent = 0;
}
printf("Discount: %d %%\n", percent);
return 0;
}
A 10-year-old should get the 50 % child discount. What does it print?
Real output:
Discount: 30 %
30 %. The child meets age <= 25 && youth_card (10 ≤ 25 and carries a card), and since that is the first true branch, the chain ends there: else if (age <= 12) is not even looked at. There is no compiler warning, because the program is correct as far as C is concerned; the bug is in the logic.
Putting the broadest condition first when two conditions overlap. The “up to 12” range sits inside “up to 25”, so it must be asked first.
With the branches in the right order:
#include <stdio.h>
int main(void) {
int age = 10;
int youth_card = 1;
int percent;
if (age <= 12) { // the most specific case first
percent = 50;
} else if (age <= 25 && youth_card) {
percent = 30;
} else {
percent = 0;
}
printf("Discount: %d %%\n", percent);
return 0;
}
Output:
Discount: 50 %
To find this kind of bug, test the edge cases: someone who meets two conditions at once (10 years old with a card), someone right on the limit (12, 13, 25, 65).
Snippet 3: the 1.10 € balance that is not 1.10 €
#include <stdio.h>
int main(void) {
float balance = 1.10f; // what is left on the card
if (balance == 1.10) { // the ticket costs 1.10
printf("Exact balance: you end up at zero\n");
} else {
printf("No match: the balance is %.10f\n", balance);
}
return 0;
}
“Exact balance” or “No match”?
Real output:
No match: the balance is 1.1000000238
It is the program from the start. 1.10 cannot be stored exactly in binary (just as 1/3 cannot be written exactly in decimal), so the computer stores the closest number it can. The problem is that balance is a float and 1.10 without an f is a double, and each type ends up with a different “closest”. When comparing, C converts the float into a double and the two numbers are no longer equal:
Comparing with == a float or double that comes from a number with decimals. It may work with some values and fail with others.
The cleanest fix for money is not to use decimals at all: store it in cents, in an int.
#include <stdio.h>
int main(void) {
int balance_cents = 110; // money in cents: integers are exact
if (balance_cents == 110) {
printf("Exact balance: you end up at zero\n");
} else {
printf("No match\n");
}
return 0;
}
Output:
Exact balance: you end up at zero
If you have to compare decimals, compare with a tolerance: if (balance - 1.10 < 0.001 && balance - 1.10 > -0.001). And if it is money, cents in an int.
Commented solutions
Solution to exercise 1
#include <stdio.h>
int main(void) {
float grade;
char letter;
float us_grade;
printf("Spanish grade (0-10): ");
// One if for both failures: if scanf fails, the || does not look at the range
if (scanf("%f", &grade) != 1 || grade < 0 || grade > 10) {
printf("Error: grade out of range\n");
return 1;
}
// Letter: from the highest to the lowest, each branch with its braces
if (grade >= 9.0f) {
letter = 'A';
} else if (grade >= 7.0f) {
letter = 'B';
} else if (grade >= 5.0f) {
letter = 'C';
} else if (grade >= 3.0f) {
letter = 'D';
} else {
letter = 'F';
}
us_grade = grade * 10; // 0-10 to 0-100: just multiply
printf("\n--- Conversions ---\n");
printf("Spanish scale: %.2f / 10\n", grade);
printf("US scale: %.2f / 100\n", us_grade);
printf("Letter grade: %c\n", letter);
printf("Status: %s\n", (grade >= 5.0f) ? "Pass" : "Fail");
return 0;
}
Why it is done this way:
- One
iffor both failures.scanf(...) != 1 || grade < 0 || grade > 10: ifscanfreads nothing, the||is already true andgrade, which would have no value, is not looked at (short-circuit). - The letter chain goes from A to F. With 7.5:
7.5 >= 9no,7.5 >= 7yes →'B', and it asks nothing more. If you started withgrade >= 3, everything except a very low fail would come out as “D”. - The 0 to 100 scale has no
if. 7.5 × 10 = 75.00. Writing five branches for that would just repeat the chain. - The status goes in a ternary because it only picks between two texts for the same
%s. - The labels have spaces to line up the values in column 21; that is why “Status:” has so many spaces after it.
With a 4.9 (another run): 4.9 >= 5 is false and 4.9 >= 3 is true, so D, and the ternary says “Fail”.
Spanish grade (0-10): 4.9 --- Conversions --- Spanish scale: 4.90 / 10 US scale: 49.00 / 100 Letter grade: D Status: Fail
Solution to exercise 2
#include <stdio.h>
int main(void) {
int a, b, c; // integer sides: so == compares without rounding errors
int largest, sum_squares, largest_squared;
printf("Side A: ");
scanf("%d", &a);
printf("Side B: ");
scanf("%d", &b);
printf("Side C: ");
scanf("%d", &c);
// Triangle inequality: each side smaller than the sum of the other two.
// With a strict > it also rules out sides that are 0 or negative
int valid = (a + b > c) && (a + c > b) && (b + c > a);
printf("\n--- Classification ---\n");
printf("Is it a valid triangle? %s\n", valid ? "Yes" : "No");
if (!valid) {
printf("Cannot classify\n");
return 1;
}
// By sides: the strictest case first (all three equal)
if (a == b && b == c) {
printf("Type by sides: Equilateral\n");
} else if (a == b || b == c || a == c) {
printf("Type by sides: Isosceles\n");
} else {
printf("Type by sides: Scalene\n");
}
// Pythagoras needs to know which side is the largest
if (a >= b && a >= c) {
largest = a;
sum_squares = b * b + c * c;
} else if (b >= a && b >= c) {
largest = b;
sum_squares = a * a + c * c;
} else {
largest = c;
sum_squares = a * a + b * b;
}
largest_squared = largest * largest;
if (largest_squared == sum_squares) {
printf("Type by angles: Right-angled\n");
} else if (largest_squared > sum_squares) {
printf("Type by angles: Obtuse\n");
} else {
printf("Type by angles: Acute\n");
}
return 0;
}
Why it is done this way:
intand notfloatfor the sides. Pythagoras compares with==, and with integers 5 × 5 = 25 and 3 × 3 + 4 × 4 = 25 are exactly equal. With decimals, snippet 3 has already shown what can happen.- Validity is stored in a variable (
valid) because it is used twice: in the ternary of theprintfand inif (!valid). - The strict
>also rules out sides that are 0 or negative. With 0, 3 and 3: 0 + 3 > 3 is false. No separateifis needed. - Equilateral first. A triangle with all three sides equal also meets
a == b || …: if isosceles came first, an equilateral would come out as “isosceles”.
The trickiest step is finding the largest side and, at the same time, adding up the squares of the other two:
// Pythagoras needs to know which side is the largest
if (a >= b && a >= c) {
largest = a;
sum_squares = b * b + c * c;
} else if (b >= a && b >= c) {
largest = b;
sum_squares = a * a + c * c;
} else {
largest = c;
sum_squares = a * a + b * b;
}
largest_squared = largest * largest;
With 3, 4 and 5: 3 >= 4 fails, so the first branch is skipped; 4 >= 3 && 4 >= 5 fails; it reaches the else: largest = 5 and sum = 3 × 3 + 4 × 4 = 9 + 16 = 25. Since 5 × 5 = 25, right-angled. Two more runs, with 2, 2 and 3 and with 1, 2 and 5:
Side A: 2 Side B: 2 Side C: 3 --- Classification --- Is it a valid triangle? Yes Type by sides: Isosceles Type by angles: Obtuse
With 2, 2 and 3: two equal sides, isosceles; the largest is 3, 3 × 3 = 9 and 2 × 2 + 2 × 2 = 8; since 9 > 8, obtuse.
Side A: 1 Side B: 2 Side C: 5 --- Classification --- Is it a valid triangle? No Cannot classify
With 1, 2 and 5: 1 + 2 = 3, which is not greater than 5. valid is 0 and the program stops before classifying.
Solution to exercise 3
#include <stdio.h>
int main(void) {
char initial;
int pin;
int logged_in = 0; // 0 = not logged in yet; 1 = correct login
printf("=== LOGIN SYSTEM ===\n");
// Attempt 1
printf("\nAttempt 1 of 3\n");
printf("User initial: ");
scanf(" %c", &initial); // the space before %c skips the pending Enter
printf("PIN: ");
scanf("%d", &pin);
if (initial == 's' && (pin == 1234 || pin == 5678 || pin == 9999)) {
logged_in = 1;
} else {
printf("✗ Wrong user or PIN\n");
}
// Attempt 2: only if the first one failed
if (!logged_in) {
printf("\nAttempt 2 of 3\n");
printf("User initial: ");
scanf(" %c", &initial);
printf("PIN: ");
scanf("%d", &pin);
if (initial == 's' && (pin == 1234 || pin == 5678 || pin == 9999)) {
logged_in = 1;
} else {
printf("✗ Wrong user or PIN\n");
}
}
// Attempt 3: the same block again (in the loops topic we will write it only once)
if (!logged_in) {
printf("\nAttempt 3 of 3\n");
printf("User initial: ");
scanf(" %c", &initial);
printf("PIN: ");
scanf("%d", &pin);
if (initial == 's' && (pin == 1234 || pin == 5678 || pin == 9999)) {
logged_in = 1;
} else {
printf("✗ Wrong user or PIN\n");
}
}
if (logged_in) {
printf("\n✓ Access granted. Welcome, sergio.\n");
printf("Access level: ");
switch (pin) { // pin is an exact number: a job for switch
case 1234:
printf("Administrator\n");
break;
case 5678:
printf("User\n");
break;
case 9999:
printf("Guest\n");
break;
}
} else {
printf("\nAccount locked: 3 failed attempts\n");
return 1;
}
return 0;
}
Why it is done this way:
logged_inworks as a switch. It starts at 0 and only a correct attempt sets it to 1. Each new attempt sits insideif (!logged_in): once logged in, the rest do not run.- The brackets in
(pin == 1234 || pin == 5678 || pin == 9999)are essential. Without them,initial == 's' && pin == 1234 || pin == 5678 || …is read as(initial == 's' && pin == 1234) || pin == 5678 || …, because&&goes before||: initialxwith PIN 5678 would get in. - The
switchonpinneeds nodefaultbecause it is only reached with one of the three valid PINs. Adding one does no harm, though. - The block is repeated three times. It is ugly on purpose: it is exactly what loops solve. In Loops in C we will write it only once.
Walkthrough of the run that succeeds at the third attempt:
| Attempt | Initial | PIN | initial == 's' | Valid PIN? | logged_in afterwards |
|---|---|---|---|---|---|
| 1 | x | 1234 | 0 | 1 | 0 |
| 2 | s | 1111 | 1 | 0 | 0 |
| 3 | s | 5678 | 1 | 1 | 1 |
At the end, logged_in is 1 and the switch jumps to case 5678: “User”.
Reading the initial with scanf("%c", &initial) without the space. In the second attempt it would read the Enter left behind by the previous PIN and the initial would be a newline.
Solution to exercise 4
#include <stdio.h>
int main(void) {
int age, youth_card, zones, hour;
int kind; // 0 normal, 1 under 4, 2 child, 3 youth, 4 senior
double base_price, percent, discount, subtotal, surcharge, total;
printf("=== BUS FARES ===\n");
printf("Age: ");
scanf("%d", &age);
printf("Do you have a youth card? (1 = yes, 0 = no): ");
scanf("%d", &youth_card);
printf("Number of zones: ");
scanf("%d", &zones);
printf("Departure hour (0-23): ");
scanf("%d", &hour);
if (zones < 1 || hour < 0 || hour > 23) {
printf("Error: data out of range\n");
return 1;
}
// 1) Base price by zones
if (zones <= 3) {
base_price = 1.50;
} else if (zones <= 6) {
base_price = 2.50;
} else {
base_price = 3.50;
}
// 2) Which discount applies. Order matters: a 10-year-old with a youth card is a child
if (age < 4) {
kind = 1;
} else if (age <= 12) {
kind = 2;
} else if (age <= 25 && youth_card) {
kind = 3;
} else if (age >= 65) {
kind = 4;
} else {
kind = 0;
}
printf("\n--- Breakdown ---\n");
printf("Base price (%d zones): %.2f €\n", zones, base_price);
// 3) kind is an exact number: switch picks the percentage and the text at once
switch (kind) {
case 1:
percent = 100;
printf("Under-4 discount: ");
break;
case 2:
percent = 50;
printf("Child discount: ");
break;
case 3:
percent = 30;
printf("Youth card discount: ");
break;
case 4:
percent = 40;
printf("Over-65 discount: ");
break;
default:
percent = 0;
printf("No discount: ");
break;
}
discount = base_price * percent / 100;
printf("-%.2f € (%.0f %%)\n", discount, percent);
subtotal = base_price - discount;
printf("Subtotal: %.2f €\n", subtotal);
// 4) Rush-hour surcharge: 7 to 9 or 17 to 19, on the subtotal
int rush_hour = (hour >= 7 && hour <= 9) || (hour >= 17 && hour <= 19);
surcharge = rush_hour ? subtotal * 0.20 : 0;
if (rush_hour) {
printf("Rush-hour surcharge: +%.2f € (20 %%)\n", surcharge);
}
total = subtotal + surcharge;
printf("TOTAL: %.2f €\n", total);
return 0;
}
Why it is done this way:
- Deciding and calculating are kept apart. The age chain only decides which discount applies and stores it in
kind. Then theswitchturns that number into a percentage and a text. That way, if the senior percentage changes, you touch a single line. - The order of the ages is the one from snippet 2: under 4 first, then up to 12 and only then the youth card.
doublefor the amounts and%.2fto show them with two decimals. Here we only do sums; no amount is compared with==.- The surcharge is worked out on the subtotal, not on the base price, and the ternary leaves it at 0 outside rush hour.
Zooming in on the switch, which picks the percentage and the text at once:
// 3) kind is an exact number: switch picks the percentage and the text at once
switch (kind) {
case 1:
percent = 100;
printf("Under-4 discount: ");
break;
case 2:
percent = 50;
printf("Child discount: ");
break;
case 3:
percent = 30;
printf("Youth card discount: ");
break;
case 4:
percent = 40;
printf("Over-65 discount: ");
break;
default:
percent = 0;
printf("No discount: ");
break;
}
discount = base_price * percent / 100;
printf("-%.2f € (%.0f %%)\n", discount, percent);
Check by hand with a 22-year-old, card, 4 zones and 8 o’clock: base price 2.50 € (4 ≤ 6); 22 is not < 4 or ≤ 12, but 22 ≤ 25 with a card → kind 3 → 30 %; 2.50 × 30 / 100 = 0.75; subtotal 2.50 − 0.75 = 1.75; 8 is between 7 and 9 → surcharge 1.75 × 0.20 = 0.35; total 1.75 + 0.35 = 2.10 €.
Two more runs. A 70-year-old woman, no card, 8 zones and at 18:
=== BUS FARES === Age: 70 Do you have a youth card? (1 = yes, 0 = no): 0 Number of zones: 8 Departure hour (0-23): 18 --- Breakdown --- Base price (8 zones): 3.50 € Over-65 discount: -1.40 € (40 %) Subtotal: 2.10 € Rush-hour surcharge: +0.42 € (20 %) TOTAL: 2.52 €
3.50 × 40 / 100 = 1.40; 3.50 − 1.40 = 2.10; 2.10 × 0.20 = 0.42; total 2.52 €. And the 10-year-old with his sister’s youth card, 2 zones, at midday:
=== BUS FARES === Age: 10 Do you have a youth card? (1 = yes, 0 = no): 1 Number of zones: 2 Departure hour (0-23): 12 --- Breakdown --- Base price (2 zones): 1.50 € Child discount: -0.75 € (50 %) Subtotal: 0.75 € TOTAL: 0.75 €
The 50 % child discount comes out, not the 30 % youth one, and at 12 there is no surcharge, so the rush-hour line does not even appear.
Watch it step by step in Python Tutor
Python Tutor runs the code line by line and shows the value of each variable at every step. Choose C as the language and paste snippet 2 exactly as it is, bug included, to watch it live:
#include <stdio.h>
int main(void) {
int age = 10;
int youth_card = 1;
int percent;
if (age <= 25 && youth_card) {
percent = 30;
} else if (age <= 12) {
percent = 50;
} else {
percent = 0;
}
printf("Discount: %d %%\n", percent);
return 0;
}
Output:
Discount: 30 %
What to watch step by step:
- The variables panel shows
age = 10andyouth_card = 1;percenthas no value yet. - When
if (age <= 25 && youth_card)is evaluated, the arrow enters the first branch: both sides of the&&are true. - After
percent = 30, the arrow jumps straight to theprintf: theelse if (age <= 12)lines never run. - Swap the first two conditions and repeat: now the arrow goes in through
age <= 12andpercentis 50.
Cheat sheet: conditionals in C
The essentials in 30 seconds: in C the condition is a number (0 = false, anything else = true) and a comparison returns 1 or 0. if / else if / else runs only the first true branch, so order matters. Always braces and never a ; after the if. == compares and = assigns. switch jumps to a case with an exact integer value and keeps going until the first break. Compile with -Wall -Wextra.
| I want… | Code | Result |
|---|---|---|
| Check a range | if (age >= 13 && age <= 25) | 1 only between 13 and 25 |
| One of two slots | (h >= 7 && h <= 9) || (h >= 17 && h <= 19) | 1 at rush hour |
| Negate | if (!logged_in) | Gets in if logged_in is 0 |
| Pick one of two values | x = (cond) ? a : b; | a if cond is not 0 |
| Store a condition | int passed = (grade >= 5); | 1 or 0 |
| Validate the input | if (scanf("%d", &n) != 1) | Gets in if no number was typed |
| Divide safely | if (d != 0 && x / d > 2) | Does not divide if d is 0 |
| Several cases, same code | case 6: case 7: …; break; | Fall-through on purpose |
| Compare a character | if (c == 's') | Single quotes |
| Compare money | if (cent == 110) | Cents in an int: exact |
Templates from the exercises:
| Exercise | Pattern | With the statement’s data |
|---|---|---|
| 1. Converter | Chain of >= from high to low + ternary | 7.5 → B, 75.00 / 100, Pass |
| 2. Triangles | valid with &&, largest side with if / else if, Pythagoras with int | 3, 4, 5 → Scalene, Right-angled |
| 3. Login | int logged_in = 0; + if (!logged_in) { … } per attempt + switch (pin) | Third attempt, 5678 → User |
| 4. Fares | Chain → kind, switch (kind) → percentage, surcharge with || | 22, card, 4 zones, 8:00 → 2.10 € |
Symptom and likely cause:
| Symptom | Likely cause |
|---|---|
The if always gets in and the variable changes value | = instead of == |
| A line runs even though the condition is false | Missing braces, or a ; after the if |
13 <= age <= 25 lets anyone through | You need two comparisons with && |
| A case never holds when it should | Chain order: a broader condition comes first |
The switch does two things | Missing break |
switch quantity not an integer | switch on a float or double |
comparison between pointer and integer | char compared with "s" instead of 's' |
Two “equal” decimals give 0 with == | float / double rounding: tolerance or cents |
Floating point exception | Division or modulo by 0 (check the (int) of the divisor) |
Before you hand it in, ask yourself:
- Have I compiled with
-Wall -Wextraand are there no warnings left? - Do all branches of every
ifhave braces, and is there no;after the bracket of anyif? - Have I tested the edge cases (the exact limit value, someone who meets two conditions at once, invalid data)?
- Does every
caseend inbreak, and does theswitchhave adefault?
With this, conditionals in C are under control. In the next topic, Loops in C, the three-attempt login will be written with a single block and the ticket machine will serve as many passengers as needed.
Keep goingAll C articlesDid this article help you? Here is how you can support SergioLearns →




What is an operating system — theory with your laptop on a study afternoon, a write() call and a CPU that never rests (and the three programs that weren’t running at the same time)