Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Control Flow Structures in C: Branching and Iteration

Tech 1

C is a structured programming language built upon three fundamental patterns: sequential execution, selection, and repetition. The language provides dedicated constructs for each pattern. Selection is implemented through if and switch, while repetition is handled by for, while, and do while.

A statement in C is an instruction terminated by a semicolon. They are categorized as expression statements, function call statements, control statements, cmopound statements enclosed in braces, and null statements. A null statement—consisting of only a semicolon—is useful where syntax requires a statement but no operation is needed.

Control statements direct program flow and are divided into three groups: conditional branches (if, switch), loops (while, for, do while), and jumps (break, goto, continue, return).

In conditional logic, C interprets any nonzero value as true and zero as false. This applies to both positive and negative numbers.

The if statement provides single, dual, or multiple paths:

if (expression)
    statement;

if (expression)
    statement1;
else
    statement2;

if (expression1)
    statement1;
else if (expression2)
    statement2;
else
    statement3;

Consider validating a score. To print a message only when the score passes:

#include <stdio.h>

int main(void)
{
    int score = 0;
    scanf("%d", &score);
    if (score >= 60)
    {
        printf("Passed\n");
    }
    return 0;
}

Adding an alternative path:

#include <stdio.h>

int main(void)
{
    int score = 0;
    scanf("%d", &score);
    if (score >= 60)
    {
        printf("Passed\n");
    }
    else
    {
        printf("Failed\n");
    }
    return 0;
}

For multiple thresholds, such as grade classification:

#include <stdio.h>

int main(void)
{
    int score = 0;
    scanf("%d", &score);

    if (score < 60)
        printf("F\n");
    else if (score < 70)
        printf("D\n");
    else if (score < 80)
        printf("C\n");
    else if (score < 90)
        printf("B\n");
    else
        printf("A\n");

    return 0;
}

A common pitfall is the dangling else. In the following snippet, the else binds to the nearest unmatched if:

int flag = 0;
int marker = 2;

if (flag == 1)
    if (marker == 2)
        printf("inner match\n");
else
    printf("outer no-match\n"); /* Executes if marker != 2 */

Adding braces removes ambiguity:

if (flag == 1)
{
    if (marker == 2)
    {
        printf("inner match\n");
    }
}
else
{
    printf("outer no-match\n");
}

To prevent accidental assignment inside conditions, place constants on the left side of equality comparisons:

/* Preferred: compile-time error if '=' is typed instead of '==' */
if (5 == value) { /* ... */ }

Two short exercises demonstrate basic branching. First, testing whether a number is odd by inspecting the remainder:

#include <stdio.h>

int main(void)
{
    int num = 0;
    scanf("%d", &num);
    if (num % 2 != 0)
        printf("Odd\n");
    else
        printf("Even\n");
    return 0;
}

Second, printing odd integers from 1 through 100. One approach checks every number:

#include <stdio.h>

int main(void)
{
    int idx = 1;
    while (idx <= 100)
    {
        if (idx % 2 != 0)
            printf("%d ", idx);
        idx++;
    }
    return 0;
}

A more efficient method increments by two:

#include <stdio.h>

int main(void)
{
    int val = 1;
    while (val <= 100)
    {
        printf("%d ", val);
        val += 2;
    }
    return 0;
}

When many discrete values determine behavior, switch is clearer than a chain of else if. It requires an integral expression and labels each branch with a constant integer:

switch (expression)
{
    case constant1:
        statements;
        break;
    case constant2:
        statements;
        break;
    default:
        statements;
        break;
}

Without break, execution falls through to the next label. Grouping cases achieves shared behavior:

#include <stdio.h>

int main(void)
{
    int day = 0;
    scanf("%d", &day);

    switch (day)
    {
        case 1: case 2: case 3: case 4: case 5:
            printf("Weekday\n");
            break;
        case 6: case 7:
            printf("Weekend\n");
            break;
        default:
            printf("Invalid\n");
            break;
    }
    return 0;
}

A default label handles unmatched values. Including it in every switch is recommended practice.

Nested switch statements are permitted. Trace this example carefully:

#include <stdio.h>

int main(void)
{
    int x = 1;
    int y = 2;

    switch (x)
    {
        case 1:
            y++;
        case 2:
            x++;
        case 3:
            switch (y)
            {
                case 1:
                    x++;
                case 2:
                    y++;
                    x++;
                    break;
            }
        case 4:
            y++;
            break;
        default:
            break;
    }
    printf("x = %d, y = %d\n", x, y);
    return 0;
}

The while loop evaluates a condition before each iteration:

while (expression)
    loop_body;

If the body must execute at least once regardless of the initial condition, do while is apprporiate:

do
{
    loop_body;
} while (expression);

Inside loops, break terminates the entire iteration immediately, while continue skips the remainder of the current pass and reevaluates the condition.

#include <stdio.h>

int main(void)
{
    int i = 1;
    while (i <= 10)
    {
        if (i == 5)
            break;      /* Output: 1 2 3 4 */
        printf("%d ", i);
        i++;
    }
    return 0;
}

With continue, placement matters. If the update statement follows continue, an infinite loop may occur:

#include <stdio.h>

int main(void)
{
    int i = 0;
    while (i < 10)
    {
        i++;
        if (i == 5)
            continue;
        printf("%d ", i);   /* Output: 1 2 3 4 6 7 8 9 10 */
    }
    return 0;
}

Character input functions interact closely with the standard input buffer. getchar reads a single character from stdin, returning its ASCII value as an int, or EOF on failure or end-of-file.

#include <stdio.h>

int main(void)
{
    int ch;
    while ((ch = getchar()) != EOF)
        putchar(ch);
    return 0;
}

Because buffered input retains the newline character, mixing scanf with getchar requires caution. After scanf reads a token, the newline remains in the buffer and would be consumed by the next character read. Flushing or explicitly consuming residual characters prevents logic errors.

Filtering digits from a stream demonstrates relational operators against ASCII boundaries:

#include <stdio.h>

int main(void)
{
    int symbol;
    while ((symbol = getchar()) != EOF)
    {
        if (symbol < '0' || symbol > '9')
            continue;
        putchar(symbol);
    }
    return 0;
}

The for loop consolidates initialization, condition, and update into one line:

for (init; condition; update)
    loop_body;

Printing values 1 through 10:

#include <stdio.h>

int main(void)
{
    for (int k = 1; k <= 10; k++)
        printf("%d ", k);
    return 0;
}

Compared with while, the for syntax keeps loop control localized, reducing errors when the update step is distant from the condition.

The goto statement performs an unconditional jump to a labeled statement within the same function. Although it can simplify breaking out of deeply nested loops during error handling, structured alternatives are generally preferred.

for (...)
    for (...)
        if (failure)
            goto cleanup;
/* ... */
cleanup:
    /* release resources */

Several problems consolidate these concepts. To compute a factorial:

#include <stdio.h>

int main(void)
{
    int n = 0;
    scanf("%d", &n);
    long long prod = 1;
    for (int k = 2; k <= n; k++)
        prod *= k;
    printf("%lld\n", prod);
    return 0;
}

Summing factorials from 1! to 10! requires resetting the intermediate product:

#include <stdio.h>

int main(void)
{
    long long sum = 0;
    long long prod = 1;

    for (int i = 1; i <= 10; i++)
    {
        prod = 1;
        for (int j = 2; j <= i; j++)
            prod *= j;
        sum += prod;
    }
    printf("%lld\n", sum);
    return 0;
}

An optimized version reuses the previous factorial:

#include <stdio.h>

int main(void)
{
    long long sum = 0;
    long long prod = 1;
    for (int i = 1; i <= 10; i++)
    {
        prod *= i;
        sum += prod;
    }
    printf("%lld\n", sum);
    return 0;
}

Binary search efficiently locates a target in a sorted array by repeatedly halving the search interval:

#include <stdio.h>

int main(void)
{
    int data[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int len = sizeof(data) / sizeof(data[0]);
    int target = 14;
    int low = 0;
    int high = len - 1;
    int found = -1;

    while (low <= high)
    {
        int mid = low + (high - low) / 2;
        if (data[mid] < target)
            low = mid + 1;
        else if (data[mid] > target)
            high = mid - 1;
        else
        {
            found = mid;
            break;
        }
    }

    if (found != -1)
        printf("Found at index %d\n", found);
    else
        printf("Not found\n");

    return 0;
}

A visual effect can be created by converging two indices from opposite ends of a string:

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

int main(void)
{
    char source[] = "Welcome!!!";
    char display[] = "**********";
    int left = 0;
    int right = strlen(source) - 1;

    while (left <= right)
    {
        display[left] = source[left];
        display[right] = source[right];
        printf("%s\n", display);
        Sleep(300);
        system("cls");
        left++;
        right--;
    }
    return 0;
}

Password verification with a limited number of attempts illustrates string comparison:

#include <stdio.h>
#include <string.h>

int main(void)
{
    char input[32];
    const char secret[] = "secret123";
    int attempts = 3;

    for (int i = 0; i < attempts; i++)
    {
        printf("Enter password: ");
        scanf("%s", input);
        if (strcmp(input, secret) == 0)
        {
            printf("Access granted\n");
            break;
        }
        else
        {
            printf("Incorrect\n");
        }
    }
    return 0;
}

Newton's method approximates square roots iteratively:

#include <stdio.h>
#include <math.h>

int main(void)
{
    double value, current, next;
    scanf("%lf", &value);
    current = value / 2.0;
    next = (current + value / current) / 2.0;

    while (fabs(next - current) >= 1e-5)
    {
        current = next;
        next = (current + value / current) / 2.0;
    }
    printf("%.3f\n", current);
    return 0;
}

Solving quadratic equations requires handling zero, positive, and negative discriminants:

#include <stdio.h>
#include <math.h>

int main(void)
{
    double a, b, c;
    while (scanf("%lf%lf%lf", &a, &b, &c) == 3)
    {
        if (fabs(a) < 1e-6)
        {
            printf("Not quadratic equation\n");
            continue;
        }
        double disc = b * b - 4.0 * a * c;
        if (fabs(disc) < 1e-6)
        {
            double root = -b / (2.0 * a);
            if (root == -0.0) root = 0.0;
            printf("x1=x2=%.2f\n", root);
        }
        else if (disc > 0)
        {
            double r1 = (-b + sqrt(disc)) / (2.0 * a);
            double r2 = (-b - sqrt(disc)) / (2.0 * a);
            if (r1 > r2)
            {
                double tmp = r1; r1 = r2; r2 = tmp;
            }
            printf("x1=%.2f;x2=%.2f\n", r1, r2);
        }
        else
        {
            double real = -b / (2.0 * a);
            double imag = sqrt(-disc) / (2.0 * a);
            printf("x1=%.2f-%.2fi;x2=%.2f+%.2fi\n", real, imag, real, imag);
        }
    }
    return 0;
}

The Leibniz formula estimates pi:

#include <stdio.h>
#include <math.h>

int main(void)
{
    double sum = 0.0;
    int sign = 1;
    int denom = 1;
    while (fabs((double)sign / denom) >= 1e-6)
    {
        sum += (double)sign / denom;
        sign = -sign;
        denom += 2;
    }
    printf("%f\n", 4.0 * sum);
    return 0;
}

Finally, a number-guessing game ties together loops, branches, and random numbers:

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

#define MAX_TRIES 10

void show_menu(void)
{
    printf("*************************\n");
    printf("*****  1. Play     ******\n");
    printf("*****  0. Exit     ******\n");
    printf("*************************\n");
}

void play_round(void)
{
    int secret = rand() % 100 + 1;
    int guess;
    int tries = MAX_TRIES;

    while (1)
    {
        printf("Remaining attempts: %d\n", tries);
        printf("Guess: ");
        scanf("%d", &guess);
        if (guess > secret)
            printf("Too high\n");
        else if (guess < secret)
            printf("Too low\n");
        else
        {
            printf("Correct!\n");
            break;
        }
        tries--;
        if (tries == 0)
        {
            printf("Out of attempts. The number was %d\n", secret);
            break;
        }
    }
}

int main(void)
{
    int choice;
    srand((unsigned int)time(NULL));

    do
    {
        show_menu();
        printf("Select: ");
        scanf("%d", &choice);
        switch (choice)
        {
            case 1:
                play_round();
                break;
            case 0:
                break;
            default:
                printf("Invalid choice\n");
                break;
        }
    } while (choice != 0);

    return 0;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.