c

examples

examples.cšŸ”§
/**
 * Pointers to Structures - Examples
 * 
 * This file demonstrates the use of pointers with structures,
 * including the arrow operator, dynamic allocation, and linked structures.
 * 
 * Compile: gcc examples.c -o examples
 * Run: ./examples
 */

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

/* ============================================================
 * EXAMPLE 1: Arrow Operator Basics
 * ============================================================ */

struct Person {
    char name[50];
    int age;
    float salary;
};

void example1_arrow_operator(void) {
    printf("=== EXAMPLE 1: Arrow Operator Basics ===\n\n");
    
    struct Person person = {"Alice", 30, 75000.0};
    struct Person *ptr = &person;
    
    printf("Accessing structure members:\n\n");
    
    // Using dot operator (with structure variable)
    printf("Using dot operator (person.member):\n");
    printf("  Name: %s\n", person.name);
    printf("  Age: %d\n", person.age);
    printf("  Salary: %.2f\n\n", person.salary);
    
    // Using arrow operator (with pointer)
    printf("Using arrow operator (ptr->member):\n");
    printf("  Name: %s\n", ptr->name);
    printf("  Age: %d\n", ptr->age);
    printf("  Salary: %.2f\n\n", ptr->salary);
    
    // Using dereference + dot (equivalent to arrow)
    printf("Using (*ptr).member (equivalent to ptr->member):\n");
    printf("  Name: %s\n", (*ptr).name);
    printf("  Age: %d\n", (*ptr).age);
    printf("  Salary: %.2f\n", (*ptr).salary);
}


/* ============================================================
 * EXAMPLE 2: Modifying Structure Through Pointer
 * ============================================================ */

void example2_modify_through_pointer(void) {
    printf("\n=== EXAMPLE 2: Modifying Through Pointer ===\n\n");
    
    struct Person person = {"Bob", 25, 50000.0};
    struct Person *ptr = &person;
    
    printf("Original values:\n");
    printf("  Name: %s, Age: %d, Salary: %.2f\n\n", 
           person.name, person.age, person.salary);
    
    // Modify through pointer
    ptr->age = 26;
    ptr->salary = 55000.0;
    strcpy(ptr->name, "Bobby");
    
    printf("After modification through pointer:\n");
    printf("  Name: %s, Age: %d, Salary: %.2f\n", 
           person.name, person.age, person.salary);
    
    printf("\nNote: Original structure was modified!\n");
}


/* ============================================================
 * EXAMPLE 3: Dynamic Structure Allocation
 * ============================================================ */

void example3_dynamic_allocation(void) {
    printf("\n=== EXAMPLE 3: Dynamic Allocation ===\n\n");
    
    // Allocate single structure
    struct Person *person = malloc(sizeof(struct Person));
    
    if (person == NULL) {
        printf("Memory allocation failed!\n");
        return;
    }
    
    // Initialize using arrow operator
    strcpy(person->name, "Charlie");
    person->age = 35;
    person->salary = 80000.0;
    
    printf("Dynamically allocated person:\n");
    printf("  Name: %s\n", person->name);
    printf("  Age: %d\n", person->age);
    printf("  Salary: %.2f\n\n", person->salary);
    
    printf("Structure address: %p\n", (void*)person);
    printf("Structure size: %zu bytes\n", sizeof(struct Person));
    
    // Free memory
    free(person);
    person = NULL;  // Good practice
    
    printf("\nMemory freed successfully.\n");
}


/* ============================================================
 * EXAMPLE 4: Array of Structures with Pointers
 * ============================================================ */

void example4_dynamic_array(void) {
    printf("\n=== EXAMPLE 4: Dynamic Array of Structures ===\n\n");
    
    int count = 3;
    
    // Allocate array of structures
    struct Person *people = malloc(count * sizeof(struct Person));
    
    if (people == NULL) {
        printf("Memory allocation failed!\n");
        return;
    }
    
    // Initialize using different methods
    // Method 1: Array notation
    strcpy(people[0].name, "Alice");
    people[0].age = 30;
    people[0].salary = 70000.0;
    
    // Method 2: Pointer arithmetic with arrow
    strcpy((people + 1)->name, "Bob");
    (people + 1)->age = 25;
    (people + 1)->salary = 55000.0;
    
    // Method 3: Using a pointer variable
    struct Person *ptr = &people[2];
    strcpy(ptr->name, "Carol");
    ptr->age = 40;
    ptr->salary = 90000.0;
    
    // Print all
    printf("%-10s %-5s %s\n", "Name", "Age", "Salary");
    printf("────────────────────────────────\n");
    
    for (int i = 0; i < count; i++) {
        printf("%-10s %-5d $%.2f\n", 
               people[i].name, people[i].age, people[i].salary);
    }
    
    // Alternative: iterate with pointer
    printf("\nUsing pointer iteration:\n");
    struct Person *end = people + count;
    for (ptr = people; ptr < end; ptr++) {
        printf("  %s is %d years old\n", ptr->name, ptr->age);
    }
    
    free(people);
}


/* ============================================================
 * EXAMPLE 5: Passing Structure by Reference
 * ============================================================ */

// Pass by value - doesn't modify original
void incrementAge_ByValue(struct Person p) {
    p.age++;
    printf("  Inside function (by value): age = %d\n", p.age);
}

// Pass by pointer - modifies original
void incrementAge_ByPointer(struct Person *p) {
    p->age++;
    printf("  Inside function (by pointer): age = %d\n", p->age);
}

// Pass by const pointer - read only
void printPerson(const struct Person *p) {
    printf("  %s, Age: %d, Salary: $%.2f\n", 
           p->name, p->age, p->salary);
}

void example5_pass_by_reference(void) {
    printf("\n=== EXAMPLE 5: Pass by Value vs Reference ===\n\n");
    
    struct Person person = {"David", 30, 60000.0};
    
    printf("Original: age = %d\n\n", person.age);
    
    printf("Passing by value:\n");
    incrementAge_ByValue(person);
    printf("  After call: age = %d (unchanged)\n\n", person.age);
    
    printf("Passing by pointer:\n");
    incrementAge_ByPointer(&person);
    printf("  After call: age = %d (modified!)\n\n", person.age);
    
    printf("Using const pointer (read-only):\n");
    printPerson(&person);
}


/* ============================================================
 * EXAMPLE 6: Returning Structure Pointer from Function
 * ============================================================ */

// Factory function - creates and returns pointer
struct Person* createPerson(const char *name, int age, float salary) {
    struct Person *p = malloc(sizeof(struct Person));
    
    if (p != NULL) {
        strncpy(p->name, name, sizeof(p->name) - 1);
        p->name[sizeof(p->name) - 1] = '\0';
        p->age = age;
        p->salary = salary;
    }
    
    return p;  // Caller is responsible for freeing
}

// Destructor function
void destroyPerson(struct Person *p) {
    if (p != NULL) {
        printf("  Destroying: %s\n", p->name);
        free(p);
    }
}

void example6_factory_function(void) {
    printf("\n=== EXAMPLE 6: Factory Pattern ===\n\n");
    
    // Create people using factory function
    struct Person *p1 = createPerson("Eve", 28, 65000.0);
    struct Person *p2 = createPerson("Frank", 45, 120000.0);
    
    if (p1 == NULL || p2 == NULL) {
        printf("Failed to create person!\n");
        destroyPerson(p1);
        destroyPerson(p2);
        return;
    }
    
    printf("Created people:\n");
    printPerson(p1);
    printPerson(p2);
    
    printf("\nCleaning up:\n");
    destroyPerson(p1);
    destroyPerson(p2);
}


/* ============================================================
 * EXAMPLE 7: Linked List with Structure Pointers
 * ============================================================ */

struct Node {
    int data;
    struct Node *next;
};

// Create new node
struct Node* createNode(int data) {
    struct Node *node = malloc(sizeof(struct Node));
    if (node != NULL) {
        node->data = data;
        node->next = NULL;
    }
    return node;
}

// Insert at front
struct Node* insertFront(struct Node *head, int data) {
    struct Node *newNode = createNode(data);
    if (newNode != NULL) {
        newNode->next = head;
    }
    return newNode;
}

// Print list
void printList(struct Node *head) {
    printf("  List: ");
    struct Node *current = head;
    while (current != NULL) {
        printf("%d", current->data);
        if (current->next != NULL) {
            printf(" -> ");
        }
        current = current->next;
    }
    printf(" -> NULL\n");
}

// Count nodes
int countNodes(struct Node *head) {
    int count = 0;
    struct Node *current = head;
    while (current != NULL) {
        count++;
        current = current->next;
    }
    return count;
}

// Free list
void freeList(struct Node *head) {
    struct Node *current = head;
    while (current != NULL) {
        struct Node *next = current->next;
        free(current);
        current = next;
    }
}

void example7_linked_list(void) {
    printf("\n=== EXAMPLE 7: Simple Linked List ===\n\n");
    
    struct Node *head = NULL;
    
    // Build list: 10 -> 20 -> 30 -> NULL
    printf("Building list...\n");
    head = insertFront(head, 30);
    printList(head);
    
    head = insertFront(head, 20);
    printList(head);
    
    head = insertFront(head, 10);
    printList(head);
    
    printf("\nList has %d nodes\n", countNodes(head));
    
    // Traverse and show addresses
    printf("\nTraversing with addresses:\n");
    struct Node *current = head;
    int index = 0;
    while (current != NULL) {
        printf("  Node[%d]: data=%d, addr=%p, next=%p\n",
               index++, current->data, (void*)current, (void*)current->next);
        current = current->next;
    }
    
    freeList(head);
    printf("\nList freed.\n");
}


/* ============================================================
 * EXAMPLE 8: Nested Structures with Pointers
 * ============================================================ */

struct Address {
    char street[100];
    char city[50];
    char zip[10];
};

struct Employee {
    char name[50];
    int id;
    struct Address *address;  // Pointer to nested structure
};

void example8_nested_pointers(void) {
    printf("\n=== EXAMPLE 8: Nested Structure Pointers ===\n\n");
    
    // Allocate employee and address separately
    struct Employee *emp = malloc(sizeof(struct Employee));
    struct Address *addr = malloc(sizeof(struct Address));
    
    if (emp == NULL || addr == NULL) {
        printf("Memory allocation failed!\n");
        free(emp);
        free(addr);
        return;
    }
    
    // Initialize address
    strcpy(addr->street, "123 Main Street");
    strcpy(addr->city, "New York");
    strcpy(addr->zip, "10001");
    
    // Initialize employee with address pointer
    strcpy(emp->name, "Grace Hopper");
    emp->id = 1001;
    emp->address = addr;
    
    // Access nested data through pointers
    printf("Employee Information:\n");
    printf("  Name: %s\n", emp->name);
    printf("  ID: %d\n", emp->id);
    printf("  Street: %s\n", emp->address->street);
    printf("  City: %s\n", emp->address->city);
    printf("  ZIP: %s\n", emp->address->zip);
    
    // Clean up (free nested first)
    free(emp->address);
    free(emp);
    printf("\nMemory freed (nested first, then parent).\n");
}


/* ============================================================
 * EXAMPLE 9: Function Pointers in Structures
 * ============================================================ */

typedef struct {
    int value;
    void (*increment)(void *self);
    void (*decrement)(void *self);
    void (*print)(const void *self);
} Counter;

void counter_increment(void *self) {
    Counter *c = (Counter*)self;
    c->value++;
}

void counter_decrement(void *self) {
    Counter *c = (Counter*)self;
    c->value--;
}

void counter_print(const void *self) {
    const Counter *c = (const Counter*)self;
    printf("  Counter value: %d\n", c->value);
}

void initCounter(Counter *c, int initial) {
    c->value = initial;
    c->increment = counter_increment;
    c->decrement = counter_decrement;
    c->print = counter_print;
}

void example9_function_pointers(void) {
    printf("\n=== EXAMPLE 9: Simulating OOP with Function Pointers ===\n\n");
    
    Counter counter;
    initCounter(&counter, 10);
    
    printf("Initial:\n");
    counter.print(&counter);
    
    printf("\nAfter 3 increments:\n");
    counter.increment(&counter);
    counter.increment(&counter);
    counter.increment(&counter);
    counter.print(&counter);
    
    printf("\nAfter 1 decrement:\n");
    counter.decrement(&counter);
    counter.print(&counter);
}


/* ============================================================
 * EXAMPLE 10: Doubly Linked List
 * ============================================================ */

struct DLLNode {
    int data;
    struct DLLNode *prev;
    struct DLLNode *next;
};

struct DLLNode* createDLLNode(int data) {
    struct DLLNode *node = malloc(sizeof(struct DLLNode));
    if (node != NULL) {
        node->data = data;
        node->prev = NULL;
        node->next = NULL;
    }
    return node;
}

void insertDLLBack(struct DLLNode **head, struct DLLNode **tail, int data) {
    struct DLLNode *newNode = createDLLNode(data);
    if (newNode == NULL) return;
    
    if (*head == NULL) {
        *head = *tail = newNode;
    } else {
        (*tail)->next = newNode;
        newNode->prev = *tail;
        *tail = newNode;
    }
}

void printDLLForward(struct DLLNode *head) {
    printf("  Forward:  NULL <-> ");
    while (head != NULL) {
        printf("%d <-> ", head->data);
        head = head->next;
    }
    printf("NULL\n");
}

void printDLLBackward(struct DLLNode *tail) {
    printf("  Backward: NULL <-> ");
    while (tail != NULL) {
        printf("%d <-> ", tail->data);
        tail = tail->prev;
    }
    printf("NULL\n");
}

void freeDLL(struct DLLNode *head) {
    while (head != NULL) {
        struct DLLNode *next = head->next;
        free(head);
        head = next;
    }
}

void example10_doubly_linked(void) {
    printf("\n=== EXAMPLE 10: Doubly Linked List ===\n\n");
    
    struct DLLNode *head = NULL;
    struct DLLNode *tail = NULL;
    
    // Insert elements
    insertDLLBack(&head, &tail, 10);
    insertDLLBack(&head, &tail, 20);
    insertDLLBack(&head, &tail, 30);
    insertDLLBack(&head, &tail, 40);
    
    printf("Doubly Linked List traversal:\n");
    printDLLForward(head);
    printDLLBackward(tail);
    
    freeDLL(head);
}


/* ============================================================
 * MAIN FUNCTION
 * ============================================================ */

int main() {
    printf("╔════════════════════════════════════════════════════════╗\n");
    printf("ā•‘      POINTERS TO STRUCTURES - EXAMPLES                 ā•‘\n");
    printf("ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n\n");
    
    example1_arrow_operator();
    example2_modify_through_pointer();
    example3_dynamic_allocation();
    example4_dynamic_array();
    example5_pass_by_reference();
    example6_factory_function();
    example7_linked_list();
    example8_nested_pointers();
    example9_function_pointers();
    example10_doubly_linked();
    
    printf("\n═══════════════════════════════════════════════════════\n");
    printf("All examples completed successfully!\n");
    
    return 0;
}
Examples - C Programming Tutorial | DeepML