Control Flow & Decision Making
Make your programs smart! Use if-else to make decisions and switch for multiple choices. Programs can now respond differently to different situations.
What You Will Learn
- āUnderstand true/false in C (0 = false, non-zero = true)
- āUse if, if-else, and else-if statements
- āMaster switch statement for multiple choices
- āKnow when to use switch vs if-else
01What is Control Flow?
Control flow determines the order in which statements are executed in a program. By default, code runs sequentially from top to bottom. Control flow statements let you make decisionsand repeat code.
| Type | Purpose | Keywords |
|---|---|---|
| Decision Making | Execute different code based on conditions | if, else, switch |
| Looping | Repeat code multiple times | for, while, do-while |
| Jump | Transfer control to another point | break, continue, goto |
š This Tutorial Covers Decision Making
This tutorial focuses on if-else and switch statements. For loops (for, while, do-while), see the Loops Tutorial.
02Understanding True and False in C
Before using if statements, you must understand how C interprets true and false. Unlike some languages, C doesn't have a built-in bool type (before C99).
šÆ The Golden Rule in C
0
= FALSE
The condition is NOT met
Code block is SKIPPED
ā 0
= TRUE
Any non-zero value
Code block EXECUTES
What Values Are True or False?
| Expression / Value | Numeric Value | Result | if() Behavior |
|---|---|---|---|
| 0 | 0 | FALSE | Block skipped |
| 1 | 1 | TRUE | Block executes |
| -1, -5, -100 | non-zero | TRUE | Block executes |
| 42, 100, 999 | non-zero | TRUE | Block executes |
| 0.0 (float) | 0 | FALSE | Block skipped |
| 3.14 (float) | non-zero | TRUE | Block executes |
| '\0' (null char) | 0 | FALSE | Block skipped |
| 'A' (any char) | 65 | TRUE | Block executes |
| NULL (pointer) | 0 | FALSE | Block skipped |
| &variable (address) | non-zero | TRUE | Block executes |
Comparison Expressions Return 0 or 1
When you use comparison operators (>, <,==, etc.), the result is always 1 (true) or 0 (false).
| Expression | Evaluates To | Meaning |
|---|---|---|
| 5 > 3 | 1 | TRUE (5 is greater than 3) |
| 5 < 3 | 0 | FALSE (5 is not less than 3) |
| 5 == 5 | 1 | TRUE (5 equals 5) |
| 5 != 5 | 0 | FALSE (5 is not different from 5) |
| 10 >= 10 | 1 | TRUE (10 is >= 10) |
| (5 > 3) && (2 < 1) | 0 | FALSE (true AND false = false) |
| (5 > 3) || (2 < 1) | 1 | TRUE (true OR false = true) |
š This program demonstrates how C evaluates different values as true or false.
1#include <stdio.h>23int main() {4 // Demonstrating true/false values5 printf("=== True/False in C ===\n\n");6 7 // Zero is FALSE8 if (0) {9 printf("0: This won't print\n");10 } else {11 printf("0: FALSE (block skipped)\n");12 }13 14 // Non-zero is TRUE15 if (1) printf("1: TRUE\n");16 if (-5) printf("-5: TRUE (negative numbers are non-zero)\n");17 if (100) printf("100: TRUE\n");18 19 // Comparison results20 printf("\n=== Comparisons Return 0 or 1 ===\n");21 printf("5 > 3 = %d (TRUE)\n", 5 > 3);22 printf("5 < 3 = %d (FALSE)\n", 5 < 3);23 printf("5 == 5 = %d (TRUE)\n", 5 == 5);24 printf("5 != 5 = %d (FALSE)\n", 5 != 5);25 26 // You can store comparison results27 int isAdult = (25 >= 18); // isAdult = 128 printf("\n25 >= 18 stored in variable: %d\n", isAdult);29 30 return 0;31}=== True/False in C ===
0: FALSE (block skipped)
1: TRUE
-5: TRUE (negative numbers are non-zero)
100: TRUE
=== Comparisons Return 0 or 1 ===
5 > 3 = 1 (TRUE)
5 < 3 = 0 (FALSE)
5 == 5 = 1 (TRUE)
5 != 5 = 0 (FALSE)
25 >= 18 stored in variable: 1
ā ļø Common Mistake: = vs ==
= is assignment, == is comparison. Writing if (x = 5) assigns 5 to x and is always TRUE (5 ā 0)!
if (x = 5) // WRONG! Assigns 5 to x, always TRUE if (x == 5) // CORRECT! Compares x to 5
03If Statement
The if statement executes a block of code only if the condition evaluates to a non-zero value (true).
Syntax
if (condition) {
// This code runs ONLY if condition is TRUE (non-zero)
}
// Code here runs regardlessš This program checks if a number is positive and prints a message only if true.
1#include <stdio.h>23int main() {4 int temperature = 35;5 6 printf("Temperature: %d°C\n", temperature);7 8 // Simple if statement9 if (temperature > 30) {10 printf("It's hot today!\n");11 printf("Consider staying hydrated.\n");12 }13 14 printf("Weather check complete.\n");15 16 return 0;17}Temperature: 35°C
It's hot today!
Consider staying hydrated.
Weather check complete.
04If-Else Statement
Add else to handle the case when the condition is FALSE. This creates two mutually exclusive paths.
Syntax
if (condition) {
// Executes if condition is TRUE (non-zero)
}
else {
// Executes if condition is FALSE (zero)
}š This program determines if a number is even or odd using if-else.
1#include <stdio.h>23int main() {4 int number = 17;5 6 printf("Number: %d\n", number);7 8 // Even numbers have remainder 0 when divided by 29 if (number % 2 == 0) {10 printf("%d is EVEN\n", number);11 }12 else {13 printf("%d is ODD\n", number);14 }15 16 return 0;17}Number: 17
17 is ODD
05Else-If Ladder
When you have multiple conditions to check, use an else-if ladder. Conditions are evaluated top-to-bottom; only the first true condition executes.
Syntax
if (condition1) {
// Runs if condition1 is TRUE
}
else if (condition2) {
// Runs if condition1 is FALSE and condition2 is TRUE
}
else if (condition3) {
// Runs if condition1, condition2 are FALSE and condition3 is TRUE
}
else {
// Runs if ALL conditions are FALSE
}š This program converts marks to letter grades using multiple conditions.
1#include <stdio.h>23int main() {4 int marks = 73;5 char grade;6 7 printf("Marks: %d\n", marks);8 9 if (marks >= 90) {10 grade = 'A';11 printf("Excellent work!\n");12 }13 else if (marks >= 80) {14 grade = 'B';15 printf("Great job!\n");16 }17 else if (marks >= 70) {18 grade = 'C';19 printf("Good effort!\n");20 }21 else if (marks >= 60) {22 grade = 'D';23 printf("You passed.\n");24 }25 else {26 grade = 'F';27 printf("Need improvement.\n");28 }29 30 printf("Grade: %c\n", grade);31 32 return 0;33}Marks: 73
Good effort!
Grade: C
š” Order Matters!
With 73 marks: We check marks >= 90 (false), then marks >= 80 (false), then marks >= 70 (TRUE!). The rest are skipped.
06Nested If Statements
You can place an if inside another if to check multiple related conditions. This is called nesting.
š This program checks if a person is eligible to vote (must be a citizen AND at least 18).
1#include <stdio.h>23int main() {4 int age = 20;5 int isCitizen = 1; // 1 = true, 0 = false6 7 printf("Age: %d, Citizen: %s\n", age, isCitizen ? "Yes" : "No");8 9 if (isCitizen) {10 // Only check age if they're a citizen11 if (age >= 18) {12 printf("ā You can vote!\n");13 }14 else {15 printf("ā Too young to vote (must be 18+).\n");16 }17 }18 else {19 printf("ā Only citizens can vote.\n");20 }21 22 return 0;23}Age: 20, Citizen: Yes
ā You can vote!
š” Simplify with Logical AND
Nested ifs can often be simplified using &&:
// Instead of nesting:
if (isCitizen && age >= 18) {
printf("You can vote!\n");
}07Switch Statement
The switch statement selects one of many code blocks based on the value of an expression. It is cleaner than multiple if-else when comparing one variable to many constant values.
Syntax
switch (expression) {
case value1:
// code for value1
break; // Exit switch
case value2:
// code for value2
break;
default:
// code if no case matches
}| Component | Description |
|---|---|
| switch(expr) | Expression must be int or char (integer types) |
| case value: | Must be a constant (not variable), unique values only |
| break; | Exits switch. Without it, execution "falls through" to next case |
| default: | Optional. Runs if no case matches (like else) |
š This program displays the day name based on a number (1-7).
1#include <stdio.h>23int main() {4 int day = 3;5 6 printf("Day number: %d\n", day);7 printf("Day name: ");8 9 switch (day) {10 case 1:11 printf("Monday\n");12 break;13 case 2:14 printf("Tuesday\n");15 break;16 case 3:17 printf("Wednesday\n");18 break;19 case 4:20 printf("Thursday\n");21 break;22 case 5:23 printf("Friday\n");24 break;25 case 6:26 printf("Saturday\n");27 break;28 case 7:29 printf("Sunday\n");30 break;31 default:32 printf("Invalid day (use 1-7)\n");33 }34 35 return 0;36}Day number: 3
Day name: Wednesday
ā ļø Don't Forget break!
Without break, execution falls through to the next case. This is sometimes intentional, but usually a bug.
Intentional Fall-Through
Sometimes fall-through is useful to group multiple cases with the same code:
š This program uses fall-through to group weekdays and weekends.
1#include <stdio.h>23int main() {4 int day = 6;5 6 printf("Day %d is a ", day);7 8 switch (day) {9 case 1:10 case 2:11 case 3:12 case 4:13 case 5:14 printf("Weekday\n");15 break;16 case 6:17 case 7:18 printf("Weekend!\n");19 break;20 default:21 printf("Invalid day\n");22 }23 24 return 0;25}Day 6 is a Weekend!
08Switch vs If-Else: When to Use Which
| Criteria | switch | if-else |
|---|---|---|
| Comparison Type | Exact value match only | Any condition (>, <, &&, etc.) |
| Data Types | int, char (integer types) | Any type (int, float, pointers) |
| Case Values | Must be constants | Can use variables |
| Range Checking | Not supported | Supported (x > 10 && x < 20) |
| Readability | Better for many exact values | Better for complex conditions |
| Performance | Often optimized to jump table | Evaluated sequentially |
ā Use switch for:
- ⢠Menu options (1, 2, 3, 4...)
- ⢠Day of week (1-7)
- ⢠Month selection
- ⢠Character commands ('a', 'b', 'c')
- ⢠Enum values
ā Use if-else for:
- ⢠Range checks (marks >= 90)
- ⢠Boolean conditions
- ⢠Comparing floats
- ⢠Complex expressions
- ⢠Variable comparisons
09Jump Statements: break, continue, goto
Jump statements transfer control to another part of the program. They interrupt the normal sequential flow of execution.
| Statement | Purpose | Used In | Effect |
|---|---|---|---|
| break | Exit immediately | loops, switch | Stops execution, exits the block |
| continue | Skip current iteration | loops only | Jumps to next iteration |
| goto | Jump to label | anywhere in function | Unconditional jump |
The break Statement
break immediately exits the innermost loop or switch statement. Execution continues with the statement following the loop/switch.
When to Use break
- āExit a switch case (required to prevent fall-through)
- āStop searching when you find what you need
- āExit an infinite loop when a condition is met
- āHandle error conditions that require early exit
š This program searches for a target value and exits the loop immediately when found.
1#include <stdio.h>23int main() {4 int numbers[] = {10, 25, 33, 47, 56, 68, 72};5 int size = 7;6 int target = 47;7 int found = 0;8 9 printf("Searching for %d...\n", target);10 11 for (int i = 0; i < size; i++) {12 printf("Checking index %d: %d\n", i, numbers[i]);13 14 if (numbers[i] == target) {15 printf(">>> Found %d at index %d!\n", target, i);16 found = 1;17 break; // Exit loop immediately - no need to check rest18 }19 }20 21 if (!found) {22 printf("Value not found.\n");23 }24 25 printf("Search complete.\n");26 return 0;27}Searching for 47...
Checking index 0: 10
Checking index 1: 25
Checking index 2: 33
Checking index 3: 47
>>> Found 47 at index 3!
Search complete.
The continue Statement
continue skips the rest of the current iteration and jumps to the next iteration of the loop. The loop itself continues running.
When to Use continue
- āSkip invalid or unwanted data
- āProcess only items matching criteria (filter)
- āAvoid deep nesting by handling edge cases early
break vs continue
break
Loop: 1 2 3 [break] done
Exits loop completely
continue
Loop: 1 2 [skip] 4 5 done
Skips to next iteration
š This program prints only positive numbers from an array, skipping negative ones.
1#include <stdio.h>23int main() {4 int numbers[] = {5, -3, 10, -7, 8, -2, 15};5 int size = 7;6 int sum = 0;7 8 printf("Processing numbers (skipping negatives):\n");9 10 for (int i = 0; i < size; i++) {11 // Skip negative numbers12 if (numbers[i] < 0) {13 printf("Skipping %d (negative)\n", numbers[i]);14 continue; // Jump to next iteration15 }16 17 // This code only runs for positive numbers18 printf("Adding %d\n", numbers[i]);19 sum += numbers[i];20 }21 22 printf("\nSum of positive numbers: %d\n", sum);23 return 0;24}Processing numbers (skipping negatives):
Adding 5
Skipping -3 (negative)
Adding 10
Skipping -7 (negative)
Adding 8
Skipping -2 (negative)
Adding 15
Sum of positive numbers: 38
The goto Statement
goto performs an unconditional jump to a labeled statement anywhere within the same function.
Syntax
goto label_name; // Jump to label
// ... other code ...
label_name: // Label definition (ends with :)
// Code continues hereā ļø Why goto is Controversial
goto is considered bad practice by most programmers because:
- ⢠Creates "spaghetti code" that's hard to read and maintain
- ⢠Makes program flow unpredictable
- ⢠Can be replaced by structured constructs (loops, functions)
- ⢠Makes debugging difficult
ā Acceptable Uses of goto
There are a few cases where goto can make code cleaner:
- 1. Breaking out of deeply nested loops - When you need to exit multiple loops at once
- 2. Centralized cleanup code - Jumping to cleanup/error handling at end of function
- 3. State machines - Some state machine implementations
š Acceptable use: Breaking out of nested loops to find a target in a 2D grid.
1#include <stdio.h>23int main() {4 int grid[3][3] = {5 {1, 2, 3},6 {4, 5, 6},7 {7, 8, 9}8 };9 int target = 5;10 int found_row = -1, found_col = -1;11 12 printf("Searching for %d in 3x3 grid...\n\n", target);13 14 // Nested loops - break would only exit inner loop15 for (int i = 0; i < 3; i++) {16 for (int j = 0; j < 3; j++) {17 printf("Checking [%d][%d] = %d\n", i, j, grid[i][j]);18 19 if (grid[i][j] == target) {20 found_row = i;21 found_col = j;22 goto found; // Exit BOTH loops at once23 }24 }25 }26 27 // Only reaches here if not found28 printf("\nValue not found in grid.\n");29 goto end;30 31found:32 printf("\n>>> Found %d at position [%d][%d]!\n", target, found_row, found_col);33 34end:35 printf("Search complete.\n");36 return 0;37}Searching for 5 in 3x3 grid...
Checking [0][0] = 1
Checking [0][1] = 2
Checking [0][2] = 3
Checking [1][0] = 4
Checking [1][1] = 5
>>> Found 5 at position [1][1]!
Search complete.
š Another acceptable use: Centralized error handling and resource cleanup.
1#include <stdio.h>2#include <stdlib.h>34int main() {5 FILE *file = NULL;6 char *buffer = NULL;7 int result = 0;8 9 // Allocate memory10 buffer = malloc(100);11 if (buffer == NULL) {12 printf("Error: Memory allocation failed\n");13 goto cleanup; // Jump to cleanup14 }15 16 // Open file17 file = fopen("data.txt", "r");18 if (file == NULL) {19 printf("Error: Cannot open file\n");20 goto cleanup; // Jump to cleanup21 }22 23 // Process file...24 printf("Processing file...\n");25 result = 1; // Success26 27cleanup: // Single cleanup point for all exits28 if (file != NULL) {29 fclose(file);30 printf("File closed.\n");31 }32 if (buffer != NULL) {33 free(buffer);34 printf("Memory freed.\n");35 }36 37 return result ? 0 : 1;38}Error: Cannot open file
Memory freed.
š” Alternatives to goto
In most cases, you can avoid goto using:
- ⢠Flag variables - Use a boolean to break out of nested loops
- ⢠Functions - Put nested loops in a function and use return
- ⢠break + flag - Set a flag before break, check in outer loop
10Common Mistakes
ā Using = instead of == in conditions
This is the most common bug! = assigns a value,== compares values.
// WRONG - assigns 5 to x, condition is always TRUE (5 != 0)if (x = 5) { printf("This always runs!\n");}// CORRECT - compares x to 5if (x == 5) { printf("x is 5\n");}ā Forgetting break in switch
Without break, execution falls through to the next case!
// WRONG - falls through to next casesswitch (day) { case 1: printf("Monday\n"); // Missing break! Falls through... case 2: printf("Tuesday\n"); // Also prints!}// CORRECTswitch (day) { case 1: printf("Monday\n"); break; // Exits switch case 2: printf("Tuesday\n"); break;}ā Semicolon after if condition
A semicolon after if() creates an empty statement!
// WRONG - semicolon makes if do nothingif (x > 5); // Empty statement!{ printf("This ALWAYS runs!\n"); // Not part of if}// CORRECTif (x > 5) { printf("x is greater than 5\n");}ā Dangling else problem
Without braces, else binds to the nearest if.
// CONFUSING - which if does else belong to?if (a > 0) if (b > 0) printf("a and b positive\n");else printf("This runs when b <= 0, NOT when a <= 0!\n");// CLEAR - use braces to show intentif (a > 0) { if (b > 0) { printf("a and b positive\n"); }} else { printf("a is not positive\n");}ā Using switch with non-constant cases
Switch case values must be compile-time constants, not variables.
int option = 2;// WRONG - case values must be constantsswitch (choice) { case option: // ERROR! Variables not allowed break;}// CORRECT - use constant valuesswitch (choice) { case 2: // Literal constant - OK break; case MAX_VALUE: // #define constant - OK break;}ā Wrong order in else-if ladder
More specific conditions should come first; otherwise, they're never reached.
int score = 95;// WRONG - first condition catches everything >= 60if (score >= 60) { printf("D\n"); // 95 matches here!} else if (score >= 70) { printf("C\n"); // Never reached for 95} else if (score >= 90) { printf("A\n"); // Never reached}// CORRECT - most specific firstif (score >= 90) { printf("A\n"); // 95 matches correctly} else if (score >= 80) { printf("B\n");} else if (score >= 60) { printf("D\n");}ā Using floats in switch
Switch only works with integer types (int, char, enum). Use if-else for floats.
float grade = 3.5;// WRONG - float not allowed in switchswitch (grade) { // ERROR! case 4.0: break;}// CORRECT - use if-else for floatsif (grade >= 4.0) { printf("A\n");} else if (grade >= 3.0) { printf("B\n");}11Summary
šÆ Key Takeaways
- ā¢TRUE/FALSE: In C, 0 = false, any non-zero value = true
- ā¢Comparisons: Return 1 (true) or 0 (false)
- ā¢if: Execute code only when condition is true
- ā¢if-else: Two paths - one for true, one for false
- ā¢else-if ladder: Check multiple conditions in order
- ā¢switch: Match exact values (int/char), don't forget break!
- ā¢break: Exit loop/switch immediately
- ā¢continue: Skip to next loop iteration
- ā¢goto: Avoid! Only use for nested loop exit or cleanup
- ā¢= vs ==: Assignment vs comparison - common bug source!
09Next Steps
Now that you understand decision making, learn how to repeat code with loops!