Control Flow
Conditional Control Statements
Master Types of if Statements and the Switch Statement using LEARNCODEGURU’s 6-level learning model.
Level 1 Basics Content
C Conditionals Overview
Decision making (also called conditional control flow) lets a program choose
different paths based on conditions. In C, the main tools are the family of
if statements and the switch statement.
This level covers every major form of if, when to use each, then
switch with case, break, and default —
plus one complete sample program.
Overview — decision making & control flow
Programs are not only sequential. Conditions test expressions that are true (non-zero) or false (zero), then run the matching statements. That is the heart of control flow for decisions.
- Condition — a relational / logical expression (e.g.
marks >= 40) - Branch — the block that runs when the condition matches
- if family — flexible for ranges, compound logic, nested checks
- switch — clear when one value maps to many discrete alternatives
Simple if
A simple if runs a statement (or block) only when the condition is true.
If the condition is false, that body is skipped and execution continues after the if.
Syntax:
if (condition) {
/* statements when condition is true */
}
Example:
int n = 12;
if (n > 0)
printf("Positive\n");
if-else
if-else chooses exactly one of two paths: the if body when true,
or the else body when false.
Syntax:
if (condition) {
/* true branch */
} else {
/* false branch */
}
Example — even / odd:
if (n % 2 == 0)
printf("Even\n");
else
printf("Odd\n");
Nested if
A nested if places an if inside another if (or else).
Use it when a second decision depends on the first being true.
Syntax idea:
if (condition1) {
if (condition2) {
/* both true */
}
}
Example:
if (age >= 18) {
if (marks >= 40)
printf("Eligible\n");
else
printf("Adult but marks low\n");
} else {
printf("Underage\n");
}
if-else-if ladder
An if-else-if ladder checks conditions in order and runs the first true branch, then skips the rest. Ideal for mutually exclusive ranges such as grades.
Syntax:
if (condition1) {
/* branch 1 */
} else if (condition2) {
/* branch 2 */
} else {
/* none matched */
}
Example — grades:
if (marks >= 90)
printf("Grade A\n");
else if (marks >= 75)
printf("Grade B\n");
else if (marks >= 60)
printf("Grade C\n");
else
printf("Grade F\n");
Comparison — when to use each if form
| Form | Best for | Avoid when |
|---|---|---|
if | Optional action; false does nothing | You need an explicit false branch |
if-else | Exactly two outcomes | Many ordered ranges (use ladder) |
Nested if | Dependent / hierarchical checks | Deep nesting without braces (hard to read) |
if-else-if | Mutually exclusive ranges / categories | One discrete value among many labels (prefer switch) |
- Prefer else-if ladders over deep nesting for grade/slab problems
- Prefer nested if when later checks only make sense after an earlier gate
- Always use braces so structure stays clear
Switch statement — syntax, case, break, default
switch compares one integral expression against a list of constant
case labels. break exits the switch; default handles
values that match no case.
Syntax:
switch (expression) {
case constant1:
/* statements */
break;
case constant2:
/* statements */
break;
default:
/* optional */
break;
}
Example — day of week:
switch (day) {
case 1: printf("Monday\n"); break;
case 2: printf("Tuesday\n"); break;
case 3: printf("Wednesday\n"); break;
case 4: printf("Thursday\n"); break;
case 5: printf("Friday\n"); break;
case 6: printf("Saturday\n"); break;
case 7: printf("Sunday\n"); break;
default: printf("Invalid day\n"); break;
}
Switch case rules (quick table)
| Element | Rule | Purpose |
|---|---|---|
case label | Must be a unique constant expression | Marks the entry point for a matching value |
break | Exits the switch immediately | Prevents falling into the next case |
default | Optional; runs when no case matches | Handles invalid / unexpected values |
| Controlling expression | Integral type (int, char, enum, …) | Value compared against each case |
case body, write break; unless you
intentionally want fall-through (covered in Level 2).
Sample program — if-else-if grade ladder
This complete program reads marks and prints a letter grade using an if-else-if ladder:
/* Conditionals — if-else-if grade sample */
#include <stdio.h>
int main(void) {
int marks;
printf("Enter marks (0-100): ");
scanf("%d", &marks);
if (marks >= 90)
printf("Grade A\n");
else if (marks >= 75)
printf("Grade B\n");
else if (marks >= 60)
printf("Grade C\n");
else if (marks >= 40)
printf("Grade D\n");
else
printf("Grade F\n");
return 0;
}
Level 2 Advanced Content
Going deeper into conditionals
Level 1 showed the forms. Level 2 explains how conditions are evaluated, the dangling-else problem, switch fall-through and limitations, when to prefer switch vs if-else-if, and the most common mistakes.
Boolean expressions — relational & logical operators
Conditions use relational operators (== != < > <= >=) and
logical operators (&& || !).
In C, zero is false; any non-zero value is true.
if (a > 0 && a < 100)— both must be true (short-circuit)if (ch == 'y' || ch == 'Y')— either is enoughif (!done)— true whendoneis zero- Prefer
==for equality; never confuse with assignment=
&& is false, the right is not evaluated —
useful for safe checks like ptr != NULL && *ptr == 0.
The dangling else problem
An else always binds to the nearest unmatched if.
Without braces, that can surprise you:
if (a)
if (b)
printf("both\n");
else
printf("which if?\n"); /* belongs to if (b) */
Fix with braces so intent is unmistakable:
if (a) {
if (b)
printf("both\n");
} else {
printf("a was false\n");
}
Nested if vs else-if ladder — clarity
- else-if ladder — exclusive alternatives; only one branch runs; easy to scan
- Nested if — later tests depend on earlier success; structure mirrors hierarchy
- Deep nesting without ladders often means you should flatten into else-if or extract functions
- For grades/slabs, ladders almost always read better than nested ifs
Switch fall-through — intentional vs accidental
Without break, control falls through to the next case.
That can be intentional (shared logic) or accidental (bug).
Intentional fall-through:
switch (code) {
case 1:
case 2:
case 3:
printf("Low priority\n");
break;
default:
printf("Other\n");
}
break after a full case body.
Always review every case for a break (or a comment marking intentional fall-through).
Switch limitations
- Controlling expression: integral types /
char/ enums — notfloatordouble caselabels must be constant expressions (not variables)- No ranges like
case 1 ... 10:in standard C (use if-else-if for ranges) - Strings cannot be switched directly — compare with
strcmpand if/else
switch vs if-else-if — when to choose
| Prefer | When | Example |
|---|---|---|
switch | One discrete value, many constant labels | Day number, menu choice, enum state |
if-else-if | Ranges, floats, complex boolean logic | Marks ≥ 90 / ≥ 75 / ≥ 60 |
| Either | Small set of equality checks on ints/chars | Operator +/- menu |
Common mistakes
- Using
=instead of==inside conditions - Missing
breakinswitch(unwanted fall-through) - Semicolon after
if (cond);creating an empty body - Forgetting braces → dangling else or wrong nesting
- Trying to
switchon afloator a variable case label
Optional flowchart — if-else-if grade flow
Visual path for assigning a grade from marks:
Level 3 C Tricky Interview Points
Advanced tricky interview points on if / else, dangling else, switch fall-through, = vs ==, and switch limitations.
Tricky Interview Point-1:
if (x = 0) is always false — assignment, not comparison
A single = assigns 0 to x and the condition value is 0 (false), so the if body never runs. Use == for comparison. Many compilers warn; treat this as a classic interview trap.
Tricky Interview Point-2:
Dangling else binds to the nearest unmatched if
In if (a) if (b) stmt1; else stmt2; the else belongs to if (b), not if (a). Always use braces { } to make nesting explicit and avoid this ambiguity.
Tricky Interview Point-3:
Missing break causes accidental fall-through
Without break, execution continues into the next case. That is intentional only when you design shared logic; otherwise it is a bug. Interviewers ask you to predict output with missing breaks.
Tricky Interview Point-4:
switch cannot test float or string ranges directly
The controlling expression must be an integral type (int, char, enum, etc.). You cannot switch on float/double, and case labels must be constant expressions — not variables or ranges like case 1..5.
Tricky Interview Point-5:
default is optional and need not be last
If no case matches and there is no default, the switch does nothing. Putting default in the middle is legal but confusing; still use break if you do not want fall-through into later cases.
Tricky Interview Point-6:
case labels must be unique compile-time constants
Duplicate case values are a compile error. Labels cannot be variables: case n: is invalid. Enums and character constants like case 'A': are fine.
Tricky Interview Point-7:
Empty if body with a trailing semicolon is a silent bug
if (n > 0); { printf("positive"); } — the semicolon ends the if with an empty statement, so the block always runs. Never put ; immediately after if (...) or while (...).
Tricky Interview Point-8:
Nested if vs else-if ladder changes which conditions run
An else-if ladder checks conditions in order and stops at the first true branch. Deep nested ifs can re-check or skip paths differently. Prefer else-if for mutually exclusive ranges (grades, tax brackets).
Tricky Interview Point-9:
Boolean in C is historically 0 / non-zero
Any non-zero value is true; zero is false. if (ptr) is idiomatic for non-null. C99 adds _Bool / bool from <stdbool.h>, but conditions still follow the zero / non-zero rule.
Tricky Interview Point-10:
switch fall-through can be intentional for shared actions
case 1: case 2: case 3: printf("low"); break; is a valid pattern — several labels share one body. Document intentional fall-through; accidental fall-through is a defect.
Tricky Interview Point-11:
Relational results are 0 or 1, usable in expressions
a > b yields 1 if true, 0 if false. You can write count += (x > 0); but prefer clear if statements in beginner code. Mixing assignment and comparison still trips people up.
Tricky Interview Point-12:
Prefer braces even for one-line if bodies
if (ok) doSomething(); looks fine until someone adds a second line without braces. Consistent braces prevent dangling-else bugs and make reviews safer — a common “best practice” interview answer.
Level 4 Simple Programs
Short programs demonstrating if-else, if-else-if, and switch.
Program 1 — if-else (even / odd)
/* if-else: even or odd */
#include <stdio.h>
int main(void) {
int n;
printf("Enter an integer: ");
scanf("%d", &n);
if (n % 2 == 0)
printf("%d is even\n", n);
else
printf("%d is odd\n", n);
return 0;
}
Program 2 — if-else-if ladder (grades)
/* if-else-if ladder: letter grade */
#include <stdio.h>
int main(void) {
int marks;
printf("Enter marks: ");
scanf("%d", &marks);
if (marks >= 90)
printf("Grade A\n");
else if (marks >= 75)
printf("Grade B\n");
else if (marks >= 60)
printf("Grade C\n");
else if (marks >= 40)
printf("Grade D\n");
else
printf("Grade F\n");
return 0;
}
Program 3 — switch (day name)
/* switch: day number to name */
#include <stdio.h>
int main(void) {
int day;
printf("Enter day (1-7): ");
scanf("%d", &day);
switch (day) {
case 1: printf("Monday\n"); break;
case 2: printf("Tuesday\n"); break;
case 3: printf("Wednesday\n"); break;
case 4: printf("Thursday\n"); break;
case 5: printf("Friday\n"); break;
case 6: printf("Saturday\n"); break;
case 7: printf("Sunday\n"); break;
default: printf("Invalid day\n"); break;
}
return 0;
}
Level 5 Problem Solving Tricks
How to master conditionals while solving problems
Most conditional bugs come from = vs ==, missing braces,
forgotten break, and choosing nested if when an else-if ladder or switch
would be clearer. Use these colorful habits every time you write a decision.
Always brace if / else / switch bodies
Write if (cond) { ... } else { ... } even for one statement. Braces kill dangling-else bugs and keep future edits safe when you add logging or a second statement.
Compare with ==; never assign inside conditions by accident
Say the condition aloud: “if n equals zero.” If you wrote =, you assigned. Prefer if (0 == n) only if your team likes Yoda style; clearer habit: pause and verify every = vs ==.
Use else-if for exclusive ranges (grades, slabs)
Marks ≥ 90, else ≥ 75, else ≥ 60 — mutually exclusive buckets fit an else-if ladder. Nested ifs that re-open every range are harder to read and easier to get wrong.
Put break after every case unless fall-through is deliberate
After writing each case body, add break immediately. If you intentionally fall through, leave a short comment: /* fall through */ so reviewers know it is not a mistake.
Choose switch for discrete values; if for ranges and floats
Day numbers, menu choices, and enum states → switch. Score bands, float thresholds, and complex boolean logic → if / else-if. Matching the tool to the problem saves bugs.
Trace switch on paper when breaks are missing
For output questions, circle the matching case, then draw an arrow downward through every following case until a break or the end of the switch. That predicts fall-through output every time.
Keep conditions simple; extract complex tests
If a condition has many && / || parts, compute a named flag first: int eligible = age >= 18 && marks >= 40; if (eligible) .... Named booleans document intent and ease debugging.
Draw a tiny flowchart before coding multi-branch logic
For if-else-if or switch menus, sketch Start → condition → Yes/No paths → End. Coding from the sketch reduces missed branches and forgotten default/else cases.
Quick success checklist
- Before run: == not =? braces present? every case has break (or intentional fall-through)?
- Debug order: fix empty if(;); → check nesting/else binding → trace switch fall-through on paper
- Choose form: ranges → else-if; discrete ints/chars → switch; dependent gates → nested if with braces
Level 6 Practice Programs List
Programming questions only — focused on types of if statements and switch.
- 1. Write a C program that reads an integer and uses a simple if to print whether it is positive.
- 2. Write a C program that uses if-else to check whether a number is even or odd.
- 3. Write a C program that uses nested if to check whether a year is a leap year (divisible by 4, with century rules).
- 4. Write a C program that uses an if-else-if ladder to assign a letter grade (A/B/C/D/F) from marks.
- 5. Write a C program that uses switch to print the day name for a day number 1–7 (with default for invalid input).
- 6. Write a C program that shows intentional switch fall-through: map several menu codes to the same message.
- 7. Write a C program that demonstrates the dangling-else problem with and without braces (print which branch runs).
- 8. Write a C program that compares if-else-if vs switch for a simple calculator menu (+, -, *, /).