c
exercises
exercises.c🔧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);
}
*/