Chapter 10Beginner

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.

18 min readUpdated 2024-12-16
ifelseelse ifswitchcasebreakdecision makingconditions

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.

TypePurposeKeywords
Decision MakingExecute different code based on conditionsif, else, switch
LoopingRepeat code multiple timesfor, while, do-while
JumpTransfer control to another pointbreak, 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 / ValueNumeric ValueResultif() Behavior
00FALSEBlock skipped
11TRUEBlock executes
-1, -5, -100non-zeroTRUEBlock executes
42, 100, 999non-zeroTRUEBlock executes
0.0 (float)0FALSEBlock skipped
3.14 (float)non-zeroTRUEBlock executes
'\0' (null char)0FALSEBlock skipped
'A' (any char)65TRUEBlock executes
NULL (pointer)0FALSEBlock skipped
&variable (address)non-zeroTRUEBlock executes

Comparison Expressions Return 0 or 1

When you use comparison operators (>, <,==, etc.), the result is always 1 (true) or 0 (false).

ExpressionEvaluates ToMeaning
5 > 31TRUE (5 is greater than 3)
5 < 30FALSE (5 is not less than 3)
5 == 51TRUE (5 equals 5)
5 != 50FALSE (5 is not different from 5)
10 >= 101TRUE (10 is >= 10)
(5 > 3) && (2 < 1)0FALSE (true AND false = false)
(5 > 3) || (2 < 1)1TRUE (true OR false = true)

šŸ“ This program demonstrates how C evaluates different values as true or false.

true_false.c
C
1#include <stdio.h>
2
3int main() {
4 // Demonstrating true/false values
5 printf("=== True/False in C ===\n\n");
6
7 // Zero is FALSE
8 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 TRUE
15 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 results
20 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 results
27 int isAdult = (25 >= 18); // isAdult = 1
28 printf("\n25 >= 18 stored in variable: %d\n", isAdult);
29
30 return 0;
31}
Output

=== 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.

simple_if.c
C
1#include <stdio.h>
2
3int main() {
4 int temperature = 35;
5
6 printf("Temperature: %d°C\n", temperature);
7
8 // Simple if statement
9 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}
Output

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.

even_odd.c
C
1#include <stdio.h>
2
3int main() {
4 int number = 17;
5
6 printf("Number: %d\n", number);
7
8 // Even numbers have remainder 0 when divided by 2
9 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}
Output

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.

grade_calculator.c
C
1#include <stdio.h>
2
3int 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}
Output

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).

nested_if.c
C
1#include <stdio.h>
2
3int main() {
4 int age = 20;
5 int isCitizen = 1; // 1 = true, 0 = false
6
7 printf("Age: %d, Citizen: %s\n", age, isCitizen ? "Yes" : "No");
8
9 if (isCitizen) {
10 // Only check age if they're a citizen
11 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}
Output

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
}
ComponentDescription
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).

switch_day.c
C
1#include <stdio.h>
2
3int 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}
Output

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.

switch_fallthrough.c
C
1#include <stdio.h>
2
3int 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}
Output

Day 6 is a Weekend!

08Switch vs If-Else: When to Use Which

Criteriaswitchif-else
Comparison TypeExact value match onlyAny condition (>, <, &&, etc.)
Data Typesint, char (integer types)Any type (int, float, pointers)
Case ValuesMust be constantsCan use variables
Range CheckingNot supportedSupported (x > 10 && x < 20)
ReadabilityBetter for many exact valuesBetter for complex conditions
PerformanceOften optimized to jump tableEvaluated 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.

StatementPurposeUsed InEffect
breakExit immediatelyloops, switchStops execution, exits the block
continueSkip current iterationloops onlyJumps to next iteration
gotoJump to labelanywhere in functionUnconditional 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.

break_search.c
C
1#include <stdio.h>
2
3int 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 rest
18 }
19 }
20
21 if (!found) {
22 printf("Value not found.\n");
23 }
24
25 printf("Search complete.\n");
26 return 0;
27}
Output

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.

continue_filter.c
C
1#include <stdio.h>
2
3int 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 numbers
12 if (numbers[i] < 0) {
13 printf("Skipping %d (negative)\n", numbers[i]);
14 continue; // Jump to next iteration
15 }
16
17 // This code only runs for positive numbers
18 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}
Output

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.

goto_nested.c
C
1#include <stdio.h>
2
3int 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 loop
15 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 once
23 }
24 }
25 }
26
27 // Only reaches here if not found
28 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}
Output

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.

goto_cleanup.c
C
1#include <stdio.h>
2#include <stdlib.h>
3
4int main() {
5 FILE *file = NULL;
6 char *buffer = NULL;
7 int result = 0;
8
9 // Allocate memory
10 buffer = malloc(100);
11 if (buffer == NULL) {
12 printf("Error: Memory allocation failed\n");
13 goto cleanup; // Jump to cleanup
14 }
15
16 // Open file
17 file = fopen("data.txt", "r");
18 if (file == NULL) {
19 printf("Error: Cannot open file\n");
20 goto cleanup; // Jump to cleanup
21 }
22
23 // Process file...
24 printf("Processing file...\n");
25 result = 1; // Success
26
27cleanup: // Single cleanup point for all exits
28 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}
Output (if file doesn't exist)

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.

main.c
C
// WRONG - assigns 5 to x, condition is always TRUE (5 != 0)
if (x = 5) {
printf("This always runs!\n");
}
// CORRECT - compares x to 5
if (x == 5) {
printf("x is 5\n");
}

āŒ Forgetting break in switch

Without break, execution falls through to the next case!

main.c
C
// WRONG - falls through to next cases
switch (day) {
case 1:
printf("Monday\n");
// Missing break! Falls through...
case 2:
printf("Tuesday\n"); // Also prints!
}
// CORRECT
switch (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!

main.c
C
// WRONG - semicolon makes if do nothing
if (x > 5); // Empty statement!
{
printf("This ALWAYS runs!\n"); // Not part of if
}
// CORRECT
if (x > 5) {
printf("x is greater than 5\n");
}

āŒ Dangling else problem

Without braces, else binds to the nearest if.

main.c
C
// 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 intent
if (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.

main.c
C
int option = 2;
// WRONG - case values must be constants
switch (choice) {
case option: // ERROR! Variables not allowed
break;
}
// CORRECT - use constant values
switch (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.

main.c
C
int score = 95;
// WRONG - first condition catches everything >= 60
if (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 first
if (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.

main.c
C
float grade = 3.5;
// WRONG - float not allowed in switch
switch (grade) { // ERROR!
case 4.0:
break;
}
// CORRECT - use if-else for floats
if (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!