Chapter 2: Control Structures and Conditional Logic - Loops, Conditions, and Random Numbers

Project Requirements

This chapter introduces control structures in C programming, including conditional statements (if-else), loops (for, while, do-while), and random number generation.

Project Analysis

  1. Learn conditional statements to make decisions in your code
  2. Use loops to repeat tasks efficiently
  3. Generate random numbers to create dynamic programs
  4. Apply these concepts to create interactive programs like grade evaluators and games

Therefore, this chapter will be organized into multiple tasks covering these concepts.

Task 1: Conditional Logic - Grade Evaluator

I. Task Presentation

Create a program that evaluates student grades based on input scores and displays the corresponding letter grade.

II. Specific Implementation

From the program segment below, it can be analyzed that:

  1. Conditional statements allow different code paths based on conditions
  2. Logical operators can combine multiple conditions
  3. If-else if-else chains are used to handle multiple conditions
#include <stdio.h>

int main() {
    float score;
    
    printf("Please enter the student's score (0-100): ");
    scanf("%f", &score);

    // Use conditional statements to determine the grade
    if (score >= 90 && score <= 100) {
        printf("Score: %.2f, Grade: A (Excellent)\n", score);
    } else if (score >= 80 && score < 90) {
        printf("Score: %.2f, Grade: B (Good)\n", score);
    } else if (score >= 70 && score < 80) {
        printf("Score: %.2f, Grade: C (Average)\n", score);
    } else if (score >= 60 && score < 70) {
        printf("Score: %.2f, Grade: D (Pass)\n", score);
    } else if (score >= 0 && score < 60) {
        printf("Score: %.2f, Grade: F (Fail)\n", score);
    } else {
        printf("Score %.2f is out of valid range (0-100)!\n", score);
    }

    return 0;
}
    

III. Relevant Knowledge

(I) Conditional Statements in C

Conditional statements allow the program to execute different code paths based on whether a condition is true or false.

1. Simple if Statement

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

2. if-else Statement

if (condition) {
    // code to execute if condition is true
} else {
    // code to execute if condition is false
}
    

3. if-else if-else Statement

if (condition1) {
    // code for condition1
} else if (condition2) {
    // code for condition2
} else if (condition3) {
    // code for condition3
} else {
    // code if none of the conditions are true
}
    

(II) Logical Operators

Examples:

#include <stdio.h>

int main() {
    int age = 20;
    int hasID = 1;  // 1 means true, 0 means false
    
    // Using AND operator
    if (age >= 18 && hasID) {
        printf("You can enter.\n");
    }
    
    // Using OR operator
    if (age >= 65 || age <= 12) {
        printf("You get a discount.\n");
    }
    
    // Using NOT operator
    if (!hasID) {
        printf("Please provide ID.\n");
    }
    
    return 0;
}
    

(III) Relational Operators

Relational operators are used to compare two values:

Common Mistake:

Be careful not to confuse = (assignment) with == (equality comparison).

if (x = 5) {   // This assigns 5 to x, then checks if x is non-zero (always true!)
    // This block will always execute
}

if (x == 5) {  // This checks if x equals 5
    // This block executes only if x equals 5
}
        

Task 2: Arrays - Organizing and Accessing Data

I. Task Presentation

Learn how to store and access multiple related values using arrays, which allow you to work with collections of data efficiently.

II. Specific Implementation

From the program segment below, it can be analyzed that:

  1. Arrays are collections of elements of the same type
  2. Array elements are accessed using indices starting from 0
  3. Arrays must be declared with a fixed size at compile time
#include <stdio.h>

int main() {
    // Declare and initialize an array with 5 integers
    int numbers[5] = {3, 5, 1, 7, 9};

    printf("=== Array Elements ===\n");

    // Print all elements using a loop
    for(int i = 0; i < 5; i++) {
        printf("Element at index %d: %d\n", i, numbers[i]);
    }

    return 0;
}
    

III. Relevant Knowledge

(I) Array Declaration and Initialization

An array is a collection of elements of the same data type stored in contiguous memory locations.

1. Declaring an Array

// Syntax: data_type array_name[array_size];
int numbers[10];        // Declares an array of 10 integers
float grades[5];        // Declares an array of 5 floats
char letters[26];       // Declares an array of 26 characters
    

2. Initializing an Array

// Method 1: Initialize at declaration
int scores[5] = {85, 90, 78, 92, 88};

// Method 2: Initialize element by element
int values[3];
values[0] = 10;
values[1] = 20;
values[2] = 30;

// Method 3: Initialize with partial values (remaining elements set to 0)
int data[5] = {1, 2, 3};  // data[0]=1, data[1]=2, data[2]=3, data[3]=0, data[4]=0
    

(II) Array Access and Common Operations

Array elements are accessed using indices starting from 0 up to (size - 1).

Examples:

#include <stdio.h>

int main() {
    int numbers[5] = {10, 20, 30, 40, 50};

    // Accessing individual elements
    printf("First element: %d\n", numbers[0]);  // Output: 10
    printf("Third element: %d\n", numbers[2]);  // Output: 30

    // Modifying an element
    numbers[1] = 25;  // Now numbers[1] is 25 instead of 20
    printf("Modified second element: %d\n", numbers[1]);  // Output: 25

    // Using a loop to access all elements
    printf("All elements:\n");
    for(int i = 0; i < 5; i++) {
        printf("numbers[%d] = %d\n", i, numbers[i]);
    }

    return 0;
}
    

Important Note:

Accessing an array element with an index that is out of bounds (less than 0 or greater than or equal to the array size) results in undefined behavior. Always ensure your loop conditions are correct to prevent array overflow.

Task 3: Loop Structures - For, While, and Do-While

I. Task Presentation

Compare and implement different loop structures to iterate through an array and search for a specific value.

II. Specific Implementation

Loops allow you to execute the same code multiple times:

  1. for loop - Use when you know the number of iterations
  2. while loop - Use when the condition needs to be checked before execution
  3. do-while loop - Use when the loop body must execute at least once
#include <stdio.h>

int main() {
    int numbers[] = {3, 5, 1, 7, 9, 2};
    int target = 7;
    int found = 0;  // 0 = false, 1 = true

    printf("=== Searching for number 7 in array ===\n");

    // Method 1: for loop
    printf("\n1. Using FOR loop:\n");
    found = 0;
    for(int i = 0; i < 6; i++) {
        printf("  Checking position %d: value = %d\n", i, numbers[i]);
        if(numbers[i] == target) {
            printf("Found at position %d!\n", i);
            found = 1;
            break;  // Quit the loop if the number is found.
        }
    }
    if(!found) printf("Not found\n");

    return 0;
}
    

III. More Loop Examples

2. Using WHILE loop:

    // Method 2: while loop
    printf("\n2. Using WHILE loop:\n");
    int i = 0;
    found = 0;
    while(i < 6) {
        printf("  Checking position %d: value = %d\n", i, numbers[i]);
        if(numbers[i] == target) {
            printf("Found at position %d!\n", i);
            found = 1;
            break;
        }
        i++;
    }
    if(!found) printf("Not found\n");
    

3. Using DO-WHILE loop:

    // Method 3: do-while loop
    printf("\n3. Using DO-WHILE loop:\n");
    i = 0;
    found = 0;
    do {
        printf("  Checking position %d: value = %d\n", i, numbers[i]);
        if(numbers[i] == target) {
            printf("Found at position %d!\n", i);
            found = 1;
            break;
        }
        i++;
    } while(i < 6);
    if(!found) printf("Not found\n");
    

IV. Relevant Knowledge

(I) Types of Loops in C

1. For Loop

for (initialization; condition; increment/decrement) {
    // statements to execute
}
    

2. While Loop

while (condition) {
    // statements to execute
    // update the variable used in condition
}
    

3. Do-While Loop

do {
    // statements to execute
    // update the variable used in condition
} while (condition);
    

Key Difference:

While loop checks condition before executing the body, whereas do-while loop executes the body at least once before checking the condition.

(II) Loop Control Statements

Example using break:

#include <stdio.h>

int main() {
    for (int i = 1; i <= 10; i++) {
        if (i == 5) {
            break;  // Exit the loop when i equals 5
        }
        printf("%d ", i);
    }
    // Output: 1 2 3 4
    printf("\n");

    return 0;
}
    

Example using continue:

#include <stdio.h>

int main() {
    for (int i = 1; i <= 10; i++) {
        if (i == 5) {
            continue;  // Skip the current iteration when i equals 5
        }
        printf("%d ", i);
    }
    // Output: 1 2 3 4 6 7 8 9 10
    printf("\n");

    return 0;
}
    

Task 4: Random Numbers and Games

I. Task Presentation

Generate random numbers to create interactive games like a number guessing game.

II. Specific Implementation

Random number generation in C:

  1. Include <stdlib.h> and <time.h> headers
  2. Use srand() with time(NULL) as seed for true randomness
  3. Use rand() to generate pseudo-random numbers
#include <stdio.h>
#include <stdlib.h>  // for rand() and srand()
#include <time.h>    // for time()

int main() {
    // Use current time as random seed
    srand((unsigned int)time(NULL));

    // Generate a random integer between 1 and 100
    int secretNumber = rand() % 100 + 1;
    int guess;
    int guessCount = 0;

    printf("Welcome to the Number Guessing Game!\n");

    // Loop until the player guesses the correct number
    do {
        printf("Enter your guess: ");
        scanf("%d", &guess);
        guessCount++;

        if (guess > secretNumber) {
            printf("Too high! Try again.\n");
        } else if (guess < secretNumber) {
            printf("Too low! Try again.\n");
        } else {
            printf("Congratulations! You guessed correctly!\n");
            printf("You took %d guesses.\n", guessCount);
        }
    } while (guess != secretNumber);

    return 0;
}
    

III. Relevant Knowledge

(I) Random Number Generation in C

Random number generation requires two main functions:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    printf("Test 1: Without srand() - same numbers every run\n");
    for(int i = 0; i < 3; i++) {
        printf("%d ", rand() % 100);  // Same sequence every program run
    }
    printf("\n");

    printf("Test 2: With fixed seed\n");
    srand(999);  // Fixed seed
    for(int i = 0; i < 3; i++) {
        printf("%d ", rand() % 100);  // Same sequence every program run
    }
    printf("\n");

    printf("Test 3: With dynamic seed - different numbers every run\n");
    srand((unsigned)time(NULL));  // Dynamic seed based on current time
    for(int i = 0; i < 3; i++) {
        printf("%d ", rand() % 100);  // Different sequence every program run
    }
    printf("\n");

    return 0;
}
    

(II) Generating Random Numbers in a Range

To generate random numbers in a specific range:

Examples:

// Random number between 0 and 9
int num = rand() % 10;

// Random number between 1 and 100
int num = rand() % 100 + 1;

// Random number between 5 and 15
int num = rand() % (15 - 5 + 1) + 5;  // same as rand() % 11 + 5
    

Important Note:

Always call srand(time(NULL)) at the beginning of your program to ensure different random numbers on each run. Without this, rand() will generate the same sequence of numbers every time.

Task 5: Advanced Control: Escape Characters and Animations

I. Task Presentation

Use special escape characters and loops to create dynamic animations in the console.

II. Specific Implementation

Escape characters are special characters that start with backslash:

  1. \n - New line
  2. \r - Carriage return
  3. \t - Tab
  4. \\ - Backslash
  5. \" - Quote
#include <stdio.h>

int main() {
    printf("=== Escape Characters Comparison ===\n\n");

    // Using \n vs \r
    printf("1. Using \\n (new line):\n");
    printf("First line\n");
    printf("Second line\n\n");

    printf("2. Using \\r (carriage return):\n");
    printf("First line");
    printf("\rSecond line\n");
    printf("Result: Second line (overwrites 'First line')\n\n");

    return 0;
}
    

III. Creating a Rotating Spinner Animation

Rotating Spinner Animation

This example uses a loop, escape character \r, and sleep function to create a dynamic loading indicator.

#include <stdio.h>
#include <stdlib.h>

#ifdef _WIN32
    #include <windows.h>
    #define SLEEP_MS(ms) Sleep(ms)
#else
    #include <unistd.h>
    #define SLEEP_MS(ms) usleep((ms) * 1000)
#endif

int main() {
    char spinner[] = {'|', '/', '-', '\\'};
    int num_frames = sizeof(spinner) / sizeof(spinner[0]);
    int frame_index = 0;

    printf("Loading ");
    
    while (1) {
        printf("\rLoading %c", spinner[frame_index]);  // \r returns to start of line
        fflush(stdout);  // Force display the output
        
        frame_index = (frame_index + 1) % num_frames;  // Cycle through frames
        SLEEP_MS(100);  // Pause for 100ms
    }
    
    return 0;  // This line never executes due to infinite loop
}
    

IV. Creating a Progress Bar Animation

Progress Bar Animation

This example combines loops, escape characters, and conditional statements to create a visual progress indicator.

#include <stdio.h>
#include <stdlib.h>

#ifdef _WIN32
    #include <windows.h>
    #define SLEEP_MS(ms) Sleep(ms)
#else
    #include <unistd.h>
    #define SLEEP_MS(ms) usleep((ms) * 1000)
#endif

int main() {
    const int bar_width = 50;
    const int total_steps = 100;

    for (int progress = 0; progress <= total_steps; ++progress) {
        printf("\r[");  // \r returns cursor to start of line

        // Calculate number of filled characters
        int filled_width = (int)((double)progress / total_steps * bar_width);

        // Print filled part
        for (int i = 0; i < filled_width; ++i) {
            printf("█");
        }

        // Print unfilled part
        for (int i = 0; i < bar_width - filled_width; ++i) {
            printf(" ");
        }

        printf("] %3d%%", progress);  // Print percentage
        fflush(stdout);  // Force display

        SLEEP_MS(80);  // Pause
    }

    printf("\nInstallation completed!\n");
    return 0;
}
    

Practice Exercise 1

【Exercise 1】Write a program that calculates the factorial of a number using a for loop.

Analysis: The factorial of a number n is the product of all positive integers less than or equal to n (n! = n × (n-1) × (n-2) × ... × 1).

Solution:

#include <stdio.h>

int main() {
    int n, i;
    long long factorial = 1;

    printf("Enter an integer: ");
    scanf("%d", &n);

    // Show error if negative
    if (n < 0) {
        printf("Error! Factorial of a negative number doesn't exist.\n");
    } else {
        // Calculate factorial using for loop
        for (i = 1; i <= n; ++i) {
            factorial *= i;
        }
        printf("Factorial of %d = %lld\n", n, factorial);
    }

    return 0;
        

Practice Exercise 2

【Exercise 2】Write a program that checks if a number is prime using a while loop.

Analysis: A prime number is a number greater than 1 that is only divisible by 1 and itself.

Solution:

#include <stdio.h>

int main() {
    int n, i = 2;
    int isPrime = 1;  // 1 means prime, 0 means not prime

    printf("Enter a positive integer: ");
    scanf("%d", &n);

    if (n <= 1) {
        isPrime = 0;
    } else {
        // Check if n is divisible by any number other than 1 and itself
        while (i <= n / 2) {
            if (n % i == 0) {
                isPrime = 0;  // n is not prime
                break;
            }
            ++i;
        }
    }

    if (isPrime == 1) {
        printf("%d is a prime number.\n", n);
    } else {
        printf("%d is not a prime number.\n", n);
    }

    return 0;
        

Practice Exercise 3

【Exercise 3】Create a simple dice rolling simulator that generates two random dice values and shows if they are equal.

Analysis: Use random number generation to simulate two dice rolls (values 1-6) and check if they match.

Solution:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    int dice1, dice2;

    // Seed the random number generator
    srand((unsigned int)time(NULL));

    printf("Rolling the dice...\n");

    // Generate random numbers between 1 and 6
    dice1 = rand() % 6 + 1;
    dice2 = rand() % 6 + 1;

    printf("Dice 1: %d\n", dice1);
    printf("Dice 2: %d\n", dice2);

    if (dice1 == dice2) {
        printf("You rolled doubles! (%d and %d)\n", dice1, dice2);
    } else {
        printf("Different values.\n");
    }

    return 0;
        

Summary of Chapter 2

Key Concepts Learned:

  1. Conditional Statements: if, if-else, and if-else-if chains for making decisions
  2. Logical Operators: && (AND), || (OR), ! (NOT) for combining conditions
  3. Relational Operators: <, <=, >, >=, ==, != for comparisons
  4. Arrays: Storing and accessing collections of data
  5. Loop Structures: for, while, and do-while loops for repetitive tasks
  6. Loop Control: break and continue for controlling loop execution
  7. Random Numbers: Using rand(), srand(), and time() for generating random values
  8. Escape Characters: Using special characters like \n and \r for formatting

Applications: