CACS151 C Programming

C ProgrammingUnit 411 min read

Control Structures: if-else, switch, nested decisions, logical operators

Unit 4 of C Programming covers decision-making constructs (if, if-else, else-if, switch-case, nested if), logical operators (&&, ||, !), and their applications in real-world scenarios, with visual traces of execution and code examples.

TAKEAWAYS:

  • Branching logic: Use if, else-if, and else to execute code conditionally based on boolean expressions.
  • Multi-way branching: switch-case simplifies decisions with discrete values (e.g., menu-driven programs).
  • Logical operators: Combine conditions using && (AND), || (OR), and ! (NOT) for complex checks.
  • Nested decisions: Embed if statements inside others to handle layered conditions (e.g., student grading with multiple criteria).
  • Short-circuiting: Logical operators evaluate lazily (e.g., A && B stops if A is false).
  • Real-world tie-ins: Decision structures power authentication (e.g., eSewa login), discounts (Daraz), and traffic routing (Pathao).

1. Introduction to Decision Making

Decision-making in programming allows the program to choose between different paths of execution based on conditions. This is the core of control structures, enabling programs to respond dynamically to input or state changes.

Why Use Control Structures?

  • Adaptability: Programs can handle varying inputs (e.g., user choices, sensor data).
  • Efficiency: Avoid unnecessary computations (e.g., skip calculations if a condition fails).
  • Readability: Organize logic clearly (e.g., switch-case for menu systems).

2. Basic if Statement

The simplest form of decision-making. Syntax:

if (condition) {
    // Code to execute if condition is true
}

Example: Check if a number is positive.

#include <stdio.h>
int main() {
    int num = -5;
    if (num > 0) {
        printf("%d is positive.\n", num);
    }
    return 0;
}

Trace:

Step num Condition (num > 0) Output
1 -5 false (none)

Visual:

flowchart TD
    A["Start"] --> B["Check: num > 0?"]
    B -->|"Yes"| C["Print 'positive'"]
    B -->|"No"| D["End"]

3. if-else and else-if

Extend if to handle multiple conditions.

  • if-else: Executes one block if the condition is true, another if false.
  • else-if: Adds more conditions to check sequentially.

Example: Grade calculator (marks out of 300).

#include <stdio.h>
int main() {
    int marks = 270;
    if (marks >= 250) {
        printf("Distinction\n");
    } else if (marks >= 200) {
        printf("First Division\n");
    } else if (marks >= 150) {
        printf("Second Division\n");
    } else {
        printf("Fail\n");
    }
    return 0;
}

Trace:

Step marks Condition Check Output
1 270 270 >= 250 → true "Distinction"
(skips rest)

Real-World Tie-In: eSewa Login System

  • Uses if-else to check:
    1. Is the username correct? (if (username == stored_username))
    2. Is the password correct? (else if (password == stored_password))
    3. Else, show "Invalid credentials."

4. Nested if Statements

Combine multiple conditions hierarchically. Useful for layered checks (e.g., authentication + permissions).

Example: Bank loan eligibility (income + credit score).

#include <stdio.h>
int main() {
    int income = 50000, credit_score = 700;
    if (income >= 30000) {
        if (credit_score >= 650) {
            printf("Loan approved!\n");
        } else {
            printf("Low credit score. Try again later.\n");
        }
    } else {
        printf("Insufficient income.\n");
    }
    return 0;
}

Trace:

flowchart TD
    A["Start"] --> B["income >= 30000?"]
    B -->|"Yes"| C["credit_score >= 650?"]
    C -->|"Yes"| D["Loan approved"]
    C -->|"No"| E["Low credit score"]
    B -->|"No"| F["Insufficient income"]

Real-World Tie-In: Pathao Driver App

  • Nested if checks:
    1. Is the driver online? (if (driver_status == "online"))
    2. Is the ride request within 5 km? (else if (distance <= 5))
    3. Else, reject the request.

5. switch-case Statement

Efficient for discrete conditions (e.g., menu options, enum values). Syntax:

switch (expression) {
    case value1:
        // Code
        break;
    case value2:
        // Code
        break;
    default:
        // Fallback
}

Key Rules:

  • break exits the switch; omit to "fall through" to the next case.
  • default handles unexpected values.

Example: Simple calculator.

#include <stdio.h>
int main() {
    char op = '+';
    int a = 10, b = 5;
    switch (op) {
        case '+':
            printf("%d + %d = %d\n", a, b, a + b);
            break;
        case '-':
            printf("%d - %d = %d\n", a, b, a - b);
            break;
        default:
            printf("Invalid operator\n");
    }
    return 0;
}

Trace:

op Case Match Output
'+' case '+' 10 + 5 = 15

Visual:

flowchart TD
    A["Start"] --> B["op = '+'?"]
    B -->|"Yes"| C["Print sum"]
    B -->|"No"| D["op = '-'?"]
    D -->|"Yes"| E["Print difference"]
    D -->|"No"| F["Invalid operator"]

Real-World Tie-In: Daraz Product Categories

  • Uses switch-case to route users to:
    switch (category) {
        case 1: goto Electronics();
        case 2: goto Clothing();
        case 3: goto Grocery();
        default: goto HomePage();
    }
    

6. Logical Operators

Combine conditions using:

  • && (AND): Both conditions must be true.
  • || (OR): At least one condition must be true.
  • ! (NOT): Inverts the condition.

Example: Login validation (username and password correct).

#include <stdio.h>
int main() {
    char username[] = "admin", password[] = "1234";
    char input_user[] = "admin", input_pass[] = "123";

    if (strcmp(username, input_user) == 0 && strcmp(password, input_pass) == 0) {
        printf("Login successful!\n");
    } else {
        printf("Invalid credentials.\n");
    }
    return 0;
}

Trace:

input_user input_pass strcmp(username, input_user) == 0 strcmp(password, input_pass) == 0 && Result Output
"admin" "123" true false false "Invalid credentials"

Short-Circuiting:

  • A && B: If A is false, B is not evaluated.
  • A || B: If A is true, B is not evaluated.

Example:

if (ptr != NULL && ptr->data > 0) { ... }  // Safe: checks NULL first.

7. Common Pitfalls and Best Practices

Mistake Fix Example
Missing break in switch Add break after each case. case 1: ... break;
Redundant conditions Use else-if instead of nested if. Prefer else if for linear checks.
Overusing switch Use if-else for ranges (e.g., grades). Avoid switch for marks >= 200.
Logical operator errors Parenthesize complex conditions. if ((x > 0) && (y < 10))

8. Comparison Table: if-else vs. switch-case

Feature if-else switch-case
Use Case Ranges, complex conditions Discrete values (int, char, enum)
Performance Slower for many conditions Faster (jump table optimization)
Readability Clear for ranges (e.g., grades) Clean for menus/options
Fallback Use else Use default
Example if (marks >= 200) switch (day) { case 1: ... }

9. Worked Example: Traffic Light Controller

Problem: Simulate a traffic light cycle (red → green → yellow → red) with a 5-second delay between states.

Solution:

#include <stdio.h>
#include <unistd.h> // for sleep()

int main() {
    int state = 1; // 1: red, 2: green, 3: yellow
    while (1) {
        switch (state) {
            case 1: // Red
                printf("Traffic Light: RED\n");
                sleep(5);
                state = 2;
                break;
            case 2: // Green
                printf("Traffic Light: GREEN\n");
                sleep(5);
                state = 3;
                break;
            case 3: // Yellow
                printf("Traffic Light: YELLOW\n");
                sleep(2);
                state = 1;
                break;
        }
    }
    return 0;
}

Trace:

flowchart LR
    A["Start"] --> B["state = 1 (RED)"] --> C["Wait 5s"] --> D["state = 2"]
    D --> E["state = 2 (GREEN)"] --> F["Wait 5s"] --> G["state = 3"]
    G --> H["state = 3 (YELLOW)"] --> I["Wait 2s"] --> J["state = 1"]

Real-World Tie-In: NTC Traffic Management System

  • Uses switch-case to cycle through signals at intersections:
    switch (current_time % 15) { // 15-second cycle
        case 0: set_light("RED");
        case 5: set_light("GREEN");
        case 10: set_light("YELLOW");
    }
    

10. Exam Tip

What Examiners Look For:

  1. Correct Syntax: Use {} even for single statements (e.g., if (x > 0) printf(...); is wrong without braces).
  2. Logical Flow: Ensure conditions are mutually exclusive where needed (e.g., else-if for grades).
  3. Edge Cases: Test boundary values (e.g., marks = 250 in a ">= 250" check).
  4. Real-World Mapping: Relate problems to scenarios like:
    • Banking: Loan approval (if-else for income + credit).
    • E-commerce: Discount eligibility (switch-case for user tiers).
    • Transport: Route selection (nested if for traffic conditions).
  5. Avoid Common Errors:
    • Forgetting break in switch (leads to "fall-through").
    • Using = instead of == in conditions (e.g., if (x = 5) assigns, not compares).

Sample Exam Question:

Write a C program to read a student’s marks in 3 subjects and display their grade using the following criteria:

  • = 250: Distinction

  • = 200: First Division

  • = 150: Second Division

  • Else: Fail Use else-if and include a message for invalid marks (< 0).

Model Answer:

#include <stdio.h>
int main() {
    int sub1, sub2, sub3, total;
    printf("Enter marks for 3 subjects: ");
    scanf("%d %d %d", &sub1, &sub2, &sub3);

    if (sub1 < 0 || sub2 < 0 || sub3 < 0) {
        printf("Invalid marks!\n");
    } else {
        total = sub1 + sub2 + sub3;
        if (total >= 250) {
            printf("Distinction\n");
        } else if (total >= 200) {
            printf("First Division\n");
        } else if (total >= 150) {
            printf("Second Division\n");
        } else {
            printf("Fail\n");
        }
    }
    return 0;
}

Key Takeaway for Exams:

  • Structure: Always write if-else in a linear or nested hierarchy, never scattered.
  • Clarity: Use comments to explain complex conditions (e.g., // Check if income >= 30k AND credit_score >= 650).
  • Testing: Mentally trace 2–3 test cases (e.g., boundary values, invalid inputs).

Based on the TU BCA syllabus for C Programming (CACS151), unit 4.

Discussion

Loading…