c

exercises

exercises.c🔧
/**
 * =============================================================================
 * Function Pointers in C - Exercises
 * =============================================================================
 * 
 * Practice exercises for function pointer concepts.
 * 
 * Compile: gcc -Wall -Wextra -std=c99 -o exercises exercises.c -lm
 * Run: ./exercises
 * 
 * =============================================================================
 */

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

// =============================================================================
// Exercise 1: Basic Function Pointer Operations
// =============================================================================
/**
 * Implement a simple calculator using function pointers.
 * 
 * 1. Create functions: add, subtract, multiply, divide, modulo
 * 2. Create a function pointer type 'Operation'
 * 3. Implement get_operation() that returns the right function based on a char
 * 4. Implement calculate() that uses the function pointer to compute result
 */

// YOUR CODE HERE: Define the Operation typedef
// typedef ...

// YOUR CODE HERE: Implement the operation functions

// YOUR CODE HERE: Implement get_operation(char op)

// YOUR CODE HERE: Implement calculate(double a, char op, double b)

void exercise1(void) {
    printf("=== Exercise 1: Basic Calculator ===\n");
    
    /*
    // Uncomment when implemented:
    printf("10 + 5 = %.2f\n", calculate(10, '+', 5));
    printf("10 - 5 = %.2f\n", calculate(10, '-', 5));
    printf("10 * 5 = %.2f\n", calculate(10, '*', 5));
    printf("10 / 5 = %.2f\n", calculate(10, '/', 5));
    printf("10 %% 3 = %.2f\n", calculate(10, '%', 3));
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 2: Array Transformation with Callbacks
// =============================================================================
/**
 * Implement a generic array transformation system:
 * 
 * 1. Create transform function type: int (*TransformFunc)(int)
 * 2. Implement transform_array(int *arr, int size, TransformFunc func)
 * 3. Create transform functions: triple, absolute, clamp_to_100
 * 4. Test with sample arrays
 */

// YOUR CODE HERE: Define TransformFunc typedef

// YOUR CODE HERE: Implement transform functions
// - triple: multiply by 3
// - absolute: return absolute value
// - clamp_to_100: if > 100 return 100, else return value

// YOUR CODE HERE: Implement transform_array()

void exercise2(void) {
    printf("=== Exercise 2: Array Transformation ===\n");
    
    /*
    // Uncomment when implemented:
    int arr1[] = {5, 10, 15, 20, 25};
    int arr2[] = {-10, 5, -20, 15, -5};
    int arr3[] = {50, 100, 150, 80, 200};
    int size = 5;
    
    printf("Original: ");
    for (int i = 0; i < size; i++) printf("%d ", arr1[i]);
    printf("\n");
    
    transform_array(arr1, size, triple);
    printf("Tripled:  ");
    for (int i = 0; i < size; i++) printf("%d ", arr1[i]);
    printf("\n\n");
    
    printf("Original: ");
    for (int i = 0; i < size; i++) printf("%d ", arr2[i]);
    printf("\n");
    
    transform_array(arr2, size, absolute);
    printf("Absolute: ");
    for (int i = 0; i < size; i++) printf("%d ", arr2[i]);
    printf("\n\n");
    
    printf("Original: ");
    for (int i = 0; i < size; i++) printf("%d ", arr3[i]);
    printf("\n");
    
    transform_array(arr3, size, clamp_to_100);
    printf("Clamped:  ");
    for (int i = 0; i < size; i++) printf("%d ", arr3[i]);
    printf("\n");
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 3: Comparison Functions for Sorting
// =============================================================================
/**
 * Implement various comparison functions for sorting:
 * 
 * 1. compare_int_asc: ascending integer comparison
 * 2. compare_int_desc: descending integer comparison
 * 3. compare_abs: compare by absolute value
 * 4. compare_string_length: compare strings by length
 * 5. compare_last_char: compare strings by last character
 * 
 * Test with qsort()
 */

// YOUR CODE HERE: Implement comparison functions

void exercise3(void) {
    printf("=== Exercise 3: Comparison Functions ===\n");
    
    /*
    // Uncomment when implemented:
    int numbers[] = {-5, 3, -1, 8, -4, 2, -7};
    int n = 7;
    
    printf("Original integers: ");
    for (int i = 0; i < n; i++) printf("%d ", numbers[i]);
    printf("\n");
    
    qsort(numbers, n, sizeof(int), compare_int_asc);
    printf("Ascending:         ");
    for (int i = 0; i < n; i++) printf("%d ", numbers[i]);
    printf("\n");
    
    qsort(numbers, n, sizeof(int), compare_int_desc);
    printf("Descending:        ");
    for (int i = 0; i < n; i++) printf("%d ", numbers[i]);
    printf("\n");
    
    int abs_nums[] = {-5, 3, -1, 8, -4, 2, -7};
    qsort(abs_nums, n, sizeof(int), compare_abs);
    printf("By absolute value: ");
    for (int i = 0; i < n; i++) printf("%d ", abs_nums[i]);
    printf("\n\n");
    
    char *words[] = {"elephant", "cat", "bird", "dog", "ant"};
    int word_count = 5;
    
    printf("Original strings: ");
    for (int i = 0; i < word_count; i++) printf("%s ", words[i]);
    printf("\n");
    
    qsort(words, word_count, sizeof(char*), compare_string_length);
    printf("By length:        ");
    for (int i = 0; i < word_count; i++) printf("%s ", words[i]);
    printf("\n");
    
    char *words2[] = {"apple", "zebra", "banana", "mango", "grape"};
    qsort(words2, 5, sizeof(char*), compare_last_char);
    printf("By last char:     ");
    for (int i = 0; i < 5; i++) printf("%s ", words2[i]);
    printf("\n");
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 4: Menu System with Function Pointers
// =============================================================================
/**
 * Create a menu-driven program:
 * 
 * 1. Define MenuItem struct with: name (string), action (function pointer)
 * 2. Create action functions: show_help, show_about, show_version, quit
 * 3. Create menu array
 * 4. Implement run_menu() to display menu and execute selected action
 */

typedef void (*MenuAction)(void);

typedef struct {
    const char *name;
    MenuAction action;
} MenuItem;

// YOUR CODE HERE: Implement action functions
void show_help(void) {
    printf("  Help: This is a demo menu system\n");
}

// YOUR CODE HERE: Implement other action functions

// YOUR CODE HERE: Create menu array and run_menu function

void exercise4(void) {
    printf("=== Exercise 4: Menu System ===\n");
    
    /*
    // Uncomment when implemented:
    // Note: This would normally loop until quit
    MenuItem menu[] = {
        {"Help", show_help},
        {"About", show_about},
        {"Version", show_version},
        {"Quit", quit}
    };
    int menu_size = 4;
    
    printf("Menu items:\n");
    for (int i = 0; i < menu_size; i++) {
        printf("  %d. %s\n", i + 1, menu[i].name);
    }
    
    printf("\nExecuting each action:\n");
    for (int i = 0; i < menu_size; i++) {
        printf("Action %d: ", i + 1);
        menu[i].action();
    }
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 5: Generic Find Function
// =============================================================================
/**
 * Implement a generic find function:
 * 
 * void* generic_find(void *array, size_t count, size_t elem_size,
 *                    const void *target, CompareFunc cmp);
 * 
 * Returns pointer to first matching element, or NULL if not found.
 * 
 * Also implement:
 * - find_all: returns count of all matching elements
 * - find_if: finds first element matching a predicate
 */

typedef int (*CompareFunc)(const void*, const void*);
typedef int (*Predicate)(const void*);

// YOUR CODE HERE: Implement generic_find

// YOUR CODE HERE: Implement find_all

// YOUR CODE HERE: Implement find_if

void exercise5(void) {
    printf("=== Exercise 5: Generic Find Function ===\n");
    
    /*
    // Uncomment when implemented:
    int numbers[] = {5, 3, 8, 3, 9, 3, 1, 7};
    int size = 8;
    int target = 3;
    
    printf("Array: ");
    for (int i = 0; i < size; i++) printf("%d ", numbers[i]);
    printf("\n");
    
    int *found = generic_find(numbers, size, sizeof(int), &target, compare_int);
    if (found) {
        printf("Found %d at index %ld\n", *found, found - numbers);
    }
    
    int count = find_all(numbers, size, sizeof(int), &target, compare_int);
    printf("Count of %d: %d\n", target, count);
    
    // Find first even number
    int *first_even = find_if(numbers, size, sizeof(int), is_even);
    if (first_even) {
        printf("First even: %d at index %ld\n", *first_even, first_even - numbers);
    }
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 6: Observer Pattern
// =============================================================================
/**
 * Implement a simple observer pattern:
 * 
 * 1. Subject holds a value and list of observers (function pointers)
 * 2. When value changes, all observers are notified
 * 3. Implement: subject_init, subject_attach, subject_detach, subject_set_value
 * 4. Create sample observers that react to value changes
 */

#define MAX_OBSERVERS 10

typedef void (*ObserverFunc)(int old_value, int new_value);

typedef struct {
    int value;
    ObserverFunc observers[MAX_OBSERVERS];
    int observer_count;
} Subject;

// YOUR CODE HERE: Implement subject functions

// YOUR CODE HERE: Implement sample observers

void exercise6(void) {
    printf("=== Exercise 6: Observer Pattern ===\n");
    
    /*
    // Uncomment when implemented:
    Subject subject;
    subject_init(&subject, 0);
    
    subject_attach(&subject, logger_observer);
    subject_attach(&subject, threshold_observer);
    subject_attach(&subject, delta_observer);
    
    printf("Setting value to 50:\n");
    subject_set_value(&subject, 50);
    
    printf("\nSetting value to 150:\n");
    subject_set_value(&subject, 150);
    
    printf("\nSetting value to 100:\n");
    subject_set_value(&subject, 100);
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 7: Chain of Responsibility
// =============================================================================
/**
 * Implement a chain of handlers:
 * 
 * 1. Each handler tries to process a request
 * 2. If it can't handle it, pass to next handler
 * 3. Handlers: handle_small (< 10), handle_medium (< 100), handle_large (>= 100)
 * 4. Implement process_request that chains handlers
 */

typedef int (*Handler)(int value);  // Returns 1 if handled, 0 if not

// YOUR CODE HERE: Implement handlers

// YOUR CODE HERE: Implement process_request with chain

void exercise7(void) {
    printf("=== Exercise 7: Chain of Responsibility ===\n");
    
    /*
    // Uncomment when implemented:
    Handler chain[] = {handle_small, handle_medium, handle_large};
    int chain_length = 3;
    
    int values[] = {5, 50, 500};
    for (int i = 0; i < 3; i++) {
        printf("Processing %d: ", values[i]);
        int handled = 0;
        for (int j = 0; j < chain_length && !handled; j++) {
            handled = chain[j](values[i]);
        }
        if (!handled) {
            printf("No handler found!\n");
        }
    }
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 8: Strategy Pattern for Discount
// =============================================================================
/**
 * Implement discount strategies for a shopping cart:
 * 
 * 1. Define DiscountStrategy function type
 * 2. Strategies: no_discount, percent_10, percent_20, fixed_50, buy_2_get_1_free
 * 3. Implement apply_discount(double price, int quantity, DiscountStrategy strategy)
 * 4. Test with various products
 */

typedef double (*DiscountStrategy)(double price, int quantity);

// YOUR CODE HERE: Implement discount strategies

// YOUR CODE HERE: Implement apply_discount

void exercise8(void) {
    printf("=== Exercise 8: Discount Strategies ===\n");
    
    /*
    // Uncomment when implemented:
    double price = 100.0;
    int quantity = 3;
    
    printf("Product: $%.2f x %d = $%.2f base price\n\n", 
           price, quantity, price * quantity);
    
    printf("No discount:     $%.2f\n", apply_discount(price, quantity, no_discount));
    printf("10%% off:         $%.2f\n", apply_discount(price, quantity, percent_10));
    printf("20%% off:         $%.2f\n", apply_discount(price, quantity, percent_20));
    printf("$50 off:         $%.2f\n", apply_discount(price, quantity, fixed_50));
    printf("Buy 2 Get 1 Free: $%.2f\n", apply_discount(price, quantity, buy_2_get_1_free));
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 9: Event Dispatcher
// =============================================================================
/**
 * Create an event dispatcher with multiple event types:
 * 
 * 1. Define EventType enum: CLICK, HOVER, KEY_PRESS, SCROLL
 * 2. Define EventHandler function type
 * 3. Implement: register_handler, unregister_handler, dispatch_event
 * 4. Support multiple handlers per event type
 */

typedef enum {
    EVENT_CLICK,
    EVENT_HOVER,
    EVENT_KEY_PRESS,
    EVENT_SCROLL,
    EVENT_TYPE_COUNT
} EventType;

typedef void (*EventHandler)(EventType type, void *data);

// YOUR CODE HERE: Implement EventDispatcher struct

// YOUR CODE HERE: Implement dispatcher functions

void exercise9(void) {
    printf("=== Exercise 9: Event Dispatcher ===\n");
    
    /*
    // Uncomment when implemented:
    EventDispatcher dispatcher;
    dispatcher_init(&dispatcher);
    
    register_handler(&dispatcher, EVENT_CLICK, click_handler1);
    register_handler(&dispatcher, EVENT_CLICK, click_handler2);
    register_handler(&dispatcher, EVENT_HOVER, hover_handler);
    register_handler(&dispatcher, EVENT_KEY_PRESS, key_handler);
    
    printf("Dispatching CLICK:\n");
    dispatch_event(&dispatcher, EVENT_CLICK, "Button1");
    
    printf("\nDispatching HOVER:\n");
    dispatch_event(&dispatcher, EVENT_HOVER, "Menu");
    
    printf("\nDispatching KEY_PRESS:\n");
    dispatch_event(&dispatcher, EVENT_KEY_PRESS, "Enter");
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Exercise 10: Virtual Method Table (VTable)
// =============================================================================
/**
 * Implement a simple virtual method table pattern:
 * 
 * 1. Create Shape "base class" with vtable
 * 2. VTable has: area(), perimeter(), describe()
 * 3. Create Rectangle and Circle "subclasses"
 * 4. Demonstrate polymorphic behavior
 */

// Forward declarations
struct Shape;

// VTable type
typedef struct {
    double (*area)(struct Shape*);
    double (*perimeter)(struct Shape*);
    void (*describe)(struct Shape*);
} ShapeVTable;

// Base "class"
typedef struct Shape {
    const char *name;
    ShapeVTable *vtable;
} Shape;

// YOUR CODE HERE: Implement Rectangle struct and functions

// YOUR CODE HERE: Implement Circle struct and functions

// YOUR CODE HERE: Implement VTables for each shape

void exercise10(void) {
    printf("=== Exercise 10: Virtual Method Table ===\n");
    
    /*
    // Uncomment when implemented:
    Rectangle rect = create_rectangle(5, 3);
    Circle circle = create_circle(4);
    
    // Use as generic Shapes (polymorphism)
    Shape *shapes[] = {(Shape*)&rect, (Shape*)&circle};
    int count = 2;
    
    for (int i = 0; i < count; i++) {
        printf("\n%s:\n", shapes[i]->name);
        shapes[i]->vtable->describe(shapes[i]);
        printf("  Area: %.2f\n", shapes[i]->vtable->area(shapes[i]));
        printf("  Perimeter: %.2f\n", shapes[i]->vtable->perimeter(shapes[i]));
    }
    */
    
    printf("(Exercise not implemented yet)\n");
    printf("\n");
}

// =============================================================================
// Main Function
// =============================================================================

int main(void) {
    printf("============================================================\n");
    printf("        FUNCTION POINTERS IN C - EXERCISES                  \n");
    printf("============================================================\n\n");
    
    exercise1();
    exercise2();
    exercise3();
    exercise4();
    exercise5();
    exercise6();
    exercise7();
    exercise8();
    exercise9();
    exercise10();
    
    printf("============================================================\n");
    printf("Implement each exercise by completing the functions above.\n");
    printf("============================================================\n");
    
    return 0;
}

// =============================================================================
// ANSWER KEY
// =============================================================================
/*
 * Solutions are provided below. Try solving the exercises first!
 */

/*
// ===== Exercise 1 Solution =====
typedef double (*Operation)(double, double);

double op_add(double a, double b) { return a + b; }
double op_sub(double a, double b) { return a - b; }
double op_mul(double a, double b) { return a * b; }
double op_div(double a, double b) { return b != 0 ? a / b : 0; }
double op_mod(double a, double b) { return fmod(a, b); }

Operation get_operation(char op) {
    switch (op) {
        case '+': return op_add;
        case '-': return op_sub;
        case '*': return op_mul;
        case '/': return op_div;
        case '%': return op_mod;
        default: return NULL;
    }
}

double calculate(double a, char op, double b) {
    Operation func = get_operation(op);
    return func ? func(a, b) : 0;
}


// ===== Exercise 2 Solution =====
typedef int (*TransformFunc)(int);

int triple(int x) { return x * 3; }
int absolute(int x) { return x < 0 ? -x : x; }
int clamp_to_100(int x) { return x > 100 ? 100 : x; }

void transform_array(int *arr, int size, TransformFunc func) {
    for (int i = 0; i < size; i++) {
        arr[i] = func(arr[i]);
    }
}


// ===== Exercise 3 Solution =====
int compare_int_asc(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}

int compare_int_desc(const void *a, const void *b) {
    return *(int*)b - *(int*)a;
}

int compare_abs(const void *a, const void *b) {
    int abs_a = abs(*(int*)a);
    int abs_b = abs(*(int*)b);
    return abs_a - abs_b;
}

int compare_string_length(const void *a, const void *b) {
    return strlen(*(char**)a) - strlen(*(char**)b);
}

int compare_last_char(const void *a, const void *b) {
    const char *s1 = *(char**)a;
    const char *s2 = *(char**)b;
    return s1[strlen(s1)-1] - s2[strlen(s2)-1];
}


// ===== Exercise 5 Solution =====
void* generic_find(void *array, size_t count, size_t elem_size,
                   const void *target, CompareFunc cmp) {
    char *ptr = (char*)array;
    for (size_t i = 0; i < count; i++) {
        if (cmp(ptr + i * elem_size, target) == 0) {
            return ptr + i * elem_size;
        }
    }
    return NULL;
}

int find_all(void *array, size_t count, size_t elem_size,
             const void *target, CompareFunc cmp) {
    char *ptr = (char*)array;
    int matches = 0;
    for (size_t i = 0; i < count; i++) {
        if (cmp(ptr + i * elem_size, target) == 0) {
            matches++;
        }
    }
    return matches;
}

void* find_if(void *array, size_t count, size_t elem_size, Predicate pred) {
    char *ptr = (char*)array;
    for (size_t i = 0; i < count; i++) {
        if (pred(ptr + i * elem_size)) {
            return ptr + i * elem_size;
        }
    }
    return NULL;
}

int is_even(const void *elem) {
    return (*(int*)elem % 2) == 0;
}


// ===== Exercise 6 Solution =====
void subject_init(Subject *s, int initial_value) {
    s->value = initial_value;
    s->observer_count = 0;
}

void subject_attach(Subject *s, ObserverFunc observer) {
    if (s->observer_count < MAX_OBSERVERS) {
        s->observers[s->observer_count++] = observer;
    }
}

void subject_set_value(Subject *s, int new_value) {
    int old_value = s->value;
    s->value = new_value;
    for (int i = 0; i < s->observer_count; i++) {
        s->observers[i](old_value, new_value);
    }
}

void logger_observer(int old_val, int new_val) {
    printf("  [Logger] Value changed from %d to %d\n", old_val, new_val);
}

void threshold_observer(int old_val, int new_val) {
    if (new_val > 100) {
        printf("  [Threshold] WARNING: Value %d exceeds 100!\n", new_val);
    }
}

void delta_observer(int old_val, int new_val) {
    printf("  [Delta] Change: %+d\n", new_val - old_val);
}


// ===== Exercise 8 Solution =====
double no_discount(double price, int quantity) {
    return price * quantity;
}

double percent_10(double price, int quantity) {
    return price * quantity * 0.9;
}

double percent_20(double price, int quantity) {
    return price * quantity * 0.8;
}

double fixed_50(double price, int quantity) {
    double total = price * quantity;
    return total > 50 ? total - 50 : 0;
}

double buy_2_get_1_free(double price, int quantity) {
    int free_items = quantity / 3;
    return price * (quantity - free_items);
}

double apply_discount(double price, int quantity, DiscountStrategy strategy) {
    return strategy(price, quantity);
}
*/
Exercises - C Programming Tutorial | DeepML