c

examples

examples.cšŸ”§
/**
 * String Arrays and Pointers - Examples
 * 
 * This file demonstrates working with arrays of strings in C.
 * 
 * Compile: gcc examples.c -o examples
 * Run: ./examples
 */

#define _POSIX_C_SOURCE 200809L  // For strdup

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

/* ============================================================
 * EXAMPLE 1: 2D Character Array vs Pointer Array
 * ============================================================ */

void example1_array_types(void) {
    printf("=== EXAMPLE 1: 2D Array vs Pointer Array ===\n\n");
    
    // Method 1: 2D Character Array (fixed size)
    char names_2d[5][20] = {
        "Alice",
        "Bob",
        "Charlie",
        "David",
        "Eve"
    };
    
    // Method 2: Array of Pointers
    const char *names_ptr[] = {
        "Alice",
        "Bob",
        "Charlie",
        "David",
        "Eve"
    };
    
    printf("--- 2D Character Array ---\n");
    printf("Size: %zu bytes (5 x 20 = 100)\n", sizeof(names_2d));
    printf("Each row: %zu bytes\n", sizeof(names_2d[0]));
    for (int i = 0; i < 5; i++) {
        printf("  names_2d[%d] = \"%s\"\n", i, names_2d[i]);
    }
    
    printf("\n--- Array of Pointers ---\n");
    printf("Size: %zu bytes (%zu pointers)\n", sizeof(names_ptr), 
           sizeof(names_ptr) / sizeof(names_ptr[0]));
    printf("Each pointer: %zu bytes\n", sizeof(names_ptr[0]));
    for (int i = 0; i < 5; i++) {
        printf("  names_ptr[%d] = \"%s\"\n", i, names_ptr[i]);
    }
    
    // Key difference: 2D array strings are modifiable
    printf("\n--- Modifiability ---\n");
    strcpy(names_2d[0], "ALICE");  // OK
    printf("Modified 2D: names_2d[0] = \"%s\"\n", names_2d[0]);
    // names_ptr[0][0] = 'a';  // UNDEFINED BEHAVIOR - string literal!
    printf("Pointer array points to read-only string literals\n");
}


/* ============================================================
 * EXAMPLE 2: Memory Layout Visualization
 * ============================================================ */

void example2_memory_layout(void) {
    printf("\n=== EXAMPLE 2: Memory Layout ===\n\n");
    
    char names_2d[3][10] = {"Alice", "Bob", "Charlie"};
    char *names_ptr[] = {"Alice", "Bob", "Charlie"};
    
    printf("--- 2D Array Memory (Contiguous) ---\n");
    printf("Base address: %p\n\n", (void*)names_2d);
    
    for (int i = 0; i < 3; i++) {
        printf("Row %d: %p  \"%s\"\n", i, (void*)names_2d[i], names_2d[i]);
        printf("  Characters: ");
        for (int j = 0; j < 10; j++) {
            if (names_2d[i][j] == '\0') {
                printf("[\\0]");
            } else {
                printf("[%c]", names_2d[i][j]);
            }
        }
        printf("\n");
    }
    
    printf("\n--- Pointer Array Memory (Scattered) ---\n");
    printf("Array base: %p\n\n", (void*)names_ptr);
    
    for (int i = 0; i < 3; i++) {
        printf("names_ptr[%d]: %p -> %p \"%s\"\n", 
               i, (void*)&names_ptr[i], (void*)names_ptr[i], names_ptr[i]);
    }
}


/* ============================================================
 * EXAMPLE 3: Accessing Elements
 * ============================================================ */

void example3_accessing(void) {
    printf("\n=== EXAMPLE 3: Accessing String Array Elements ===\n\n");
    
    char *words[] = {"Hello", "World", "C"};
    int count = sizeof(words) / sizeof(words[0]);
    
    printf("Array: {\"Hello\", \"World\", \"C\"}\n\n");
    
    printf("--- Accessing Strings ---\n");
    printf("words[0] = \"%s\"\n", words[0]);
    printf("words[1] = \"%s\"\n", words[1]);
    printf("words[2] = \"%s\"\n\n", words[2]);
    
    printf("--- Accessing Characters ---\n");
    printf("words[0][0] = '%c'\n", words[0][0]);  // 'H'
    printf("words[0][1] = '%c'\n", words[0][1]);  // 'e'
    printf("words[1][0] = '%c'\n\n", words[1][0]); // 'W'
    
    printf("--- Using Pointer Notation ---\n");
    printf("*words[0] = '%c' (first char of first string)\n", *words[0]);
    printf("*(words[0]+1) = '%c'\n", *(words[0]+1));
    printf("**(words+1) = '%c' (first char of second string)\n\n", **(words+1));
    
    printf("--- Iterating Methods ---\n");
    
    // Method 1: Index-based
    printf("Index-based: ");
    for (int i = 0; i < count; i++) {
        printf("%s ", words[i]);
    }
    printf("\n");
    
    // Method 2: Pointer-based
    printf("Pointer-based: ");
    char **ptr = words;
    for (int i = 0; i < count; i++) {
        printf("%s ", *ptr++);
    }
    printf("\n");
}


/* ============================================================
 * EXAMPLE 4: Dynamic String Array Allocation
 * ============================================================ */

char **create_string_array(int count, int max_len) {
    char **arr = malloc(count * sizeof(char *));
    if (arr == NULL) return NULL;
    
    for (int i = 0; i < count; i++) {
        arr[i] = malloc(max_len * sizeof(char));
        if (arr[i] == NULL) {
            // Cleanup on failure
            for (int j = 0; j < i; j++) {
                free(arr[j]);
            }
            free(arr);
            return NULL;
        }
        arr[i][0] = '\0';  // Initialize as empty string
    }
    
    return arr;
}

void free_string_array(char **arr, int count) {
    if (arr == NULL) return;
    
    for (int i = 0; i < count; i++) {
        free(arr[i]);
    }
    free(arr);
}

void example4_dynamic_allocation(void) {
    printf("\n=== EXAMPLE 4: Dynamic String Array Allocation ===\n\n");
    
    int count = 5;
    int max_len = 50;
    
    printf("Allocating array of %d strings, max length %d\n\n", 
           count, max_len);
    
    // Allocate
    char **names = create_string_array(count, max_len);
    if (names == NULL) {
        printf("Allocation failed!\n");
        return;
    }
    
    // Populate
    strcpy(names[0], "Alice");
    strcpy(names[1], "Bob");
    strcpy(names[2], "Charlie");
    strcpy(names[3], "David");
    strcpy(names[4], "Eve");
    
    printf("Populated strings:\n");
    for (int i = 0; i < count; i++) {
        printf("  names[%d] = \"%s\"\n", i, names[i]);
    }
    
    // Modify
    strcpy(names[0], "ALICE (Modified)");
    printf("\nAfter modification:\n");
    printf("  names[0] = \"%s\"\n", names[0]);
    
    // Free
    free_string_array(names, count);
    printf("\nMemory freed successfully.\n");
}


/* ============================================================
 * EXAMPLE 5: Using strdup() for Dynamic Strings
 * ============================================================ */

void example5_strdup(void) {
    printf("\n=== EXAMPLE 5: Using strdup() ===\n\n");
    
    int count = 4;
    char **words = malloc(count * sizeof(char *));
    
    if (words == NULL) {
        printf("Allocation failed!\n");
        return;
    }
    
    // strdup allocates exact size needed
    words[0] = strdup("Short");
    words[1] = strdup("Medium length string");
    words[2] = strdup("This is a longer string example");
    words[3] = strdup("Hi");
    
    printf("Strings created with strdup:\n");
    for (int i = 0; i < count; i++) {
        printf("  [%d] \"%s\" (len=%zu)\n", 
               i, words[i], strlen(words[i]));
    }
    
    // Memory is allocated individually
    printf("\nNote: Each string has its own allocation.\n");
    
    // Cleanup
    for (int i = 0; i < count; i++) {
        free(words[i]);
    }
    free(words);
    
    printf("Memory freed.\n");
}


/* ============================================================
 * EXAMPLE 6: Sorting String Arrays
 * ============================================================ */

void bubble_sort_strings(char **arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (strcmp(arr[j], arr[j + 1]) > 0) {
                // Swap pointers (very efficient)
                char *temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

// Comparison function for qsort
int compare_strings(const void *a, const void *b) {
    return strcmp(*(const char **)a, *(const char **)b);
}

// Case-insensitive comparison
int compare_strings_nocase(const void *a, const void *b) {
    return strcasecmp(*(const char **)a, *(const char **)b);
}

void example6_sorting(void) {
    printf("\n=== EXAMPLE 6: Sorting String Arrays ===\n\n");
    
    char *names1[] = {"Charlie", "Alice", "Eve", "Bob", "David"};
    int count = 5;
    
    printf("--- Bubble Sort ---\n");
    printf("Before: ");
    for (int i = 0; i < count; i++) printf("%s ", names1[i]);
    printf("\n");
    
    bubble_sort_strings(names1, count);
    
    printf("After:  ");
    for (int i = 0; i < count; i++) printf("%s ", names1[i]);
    printf("\n\n");
    
    // Using qsort
    char *names2[] = {"banana", "Apple", "cherry", "Date"};
    count = 4;
    
    printf("--- qsort (case-sensitive) ---\n");
    printf("Before: ");
    for (int i = 0; i < count; i++) printf("%s ", names2[i]);
    printf("\n");
    
    qsort(names2, count, sizeof(char *), compare_strings);
    
    printf("After:  ");
    for (int i = 0; i < count; i++) printf("%s ", names2[i]);
    printf("\n\n");
    
    // Case-insensitive sort
    char *names3[] = {"banana", "Apple", "cherry", "Date"};
    
    printf("--- qsort (case-insensitive) ---\n");
    printf("Before: ");
    for (int i = 0; i < count; i++) printf("%s ", names3[i]);
    printf("\n");
    
    qsort(names3, count, sizeof(char *), compare_strings_nocase);
    
    printf("After:  ");
    for (int i = 0; i < count; i++) printf("%s ", names3[i]);
    printf("\n");
}


/* ============================================================
 * EXAMPLE 7: Searching String Arrays
 * ============================================================ */

int linear_search(char **arr, int n, const char *target) {
    for (int i = 0; i < n; i++) {
        if (strcmp(arr[i], target) == 0) {
            return i;
        }
    }
    return -1;
}

int binary_search_string(char **arr, int n, const char *target) {
    int left = 0, right = n - 1;
    
    while (left <= right) {
        int mid = left + (right - left) / 2;
        int cmp = strcmp(arr[mid], target);
        
        if (cmp == 0) {
            return mid;
        } else if (cmp < 0) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    
    return -1;
}

void example7_searching(void) {
    printf("\n=== EXAMPLE 7: Searching String Arrays ===\n\n");
    
    char *names[] = {"Alice", "Bob", "Charlie", "David", "Eve"};
    int count = 5;
    
    printf("Array: ");
    for (int i = 0; i < count; i++) printf("%s ", names[i]);
    printf("\n\n");
    
    printf("--- Linear Search ---\n");
    int idx = linear_search(names, count, "Charlie");
    printf("Search for \"Charlie\": index %d\n", idx);
    
    idx = linear_search(names, count, "Frank");
    printf("Search for \"Frank\": index %d (not found)\n\n", idx);
    
    printf("--- Binary Search (sorted array) ---\n");
    // Already sorted alphabetically
    idx = binary_search_string(names, count, "David");
    printf("Search for \"David\": index %d\n", idx);
    
    idx = binary_search_string(names, count, "Alice");
    printf("Search for \"Alice\": index %d\n", idx);
    
    idx = binary_search_string(names, count, "Zack");
    printf("Search for \"Zack\": index %d (not found)\n", idx);
}


/* ============================================================
 * EXAMPLE 8: Command Line Arguments Simulation
 * ============================================================ */

void process_args(int argc, char *argv[]) {
    printf("Program: %s\n", argv[0]);
    printf("Argument count: %d\n\n", argc);
    
    int verbose = 0;
    const char *filename = NULL;
    
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-v") == 0 || 
            strcmp(argv[i], "--verbose") == 0) {
            verbose = 1;
        } else if ((strcmp(argv[i], "-f") == 0 || 
                    strcmp(argv[i], "--file") == 0) && i + 1 < argc) {
            filename = argv[++i];
        } else if (argv[i][0] != '-') {
            printf("Positional argument: %s\n", argv[i]);
        } else {
            printf("Unknown option: %s\n", argv[i]);
        }
    }
    
    printf("\nParsed options:\n");
    printf("  Verbose: %s\n", verbose ? "yes" : "no");
    printf("  Filename: %s\n", filename ? filename : "(not specified)");
}

void example8_command_line(void) {
    printf("\n=== EXAMPLE 8: Command Line Arguments ===\n\n");
    
    // Simulate different command line invocations
    printf("--- Simulation 1: Basic usage ---\n");
    char *args1[] = {"./myprogram", "input.txt", "-v"};
    process_args(3, args1);
    
    printf("\n--- Simulation 2: With file option ---\n");
    char *args2[] = {"./myprogram", "-f", "data.txt", "--verbose"};
    process_args(4, args2);
}


/* ============================================================
 * EXAMPLE 9: NULL-Terminated String Arrays
 * ============================================================ */

void print_null_terminated(char **arr) {
    int count = 0;
    while (*arr != NULL) {
        printf("[%d] %s\n", count++, *arr);
        arr++;
    }
    printf("Total: %d strings\n", count);
}

void example9_null_terminated(void) {
    printf("\n=== EXAMPLE 9: NULL-Terminated String Arrays ===\n\n");
    
    // NULL-terminated array (no need to pass size)
    char *colors[] = {"red", "green", "blue", "yellow", NULL};
    
    printf("Colors array (NULL-terminated):\n");
    print_null_terminated(colors);
    
    printf("\n--- Iterating with different methods ---\n");
    
    // Method 1: Check against NULL
    printf("Method 1: ");
    for (int i = 0; colors[i] != NULL; i++) {
        printf("%s ", colors[i]);
    }
    printf("\n");
    
    // Method 2: Using pointer
    printf("Method 2: ");
    char **ptr = colors;
    while (*ptr) {
        printf("%s ", *ptr++);
    }
    printf("\n");
}


/* ============================================================
 * EXAMPLE 10: Tokenizing into String Array
 * ============================================================ */

int tokenize(char *str, char *tokens[], int max, const char *delim) {
    int count = 0;
    char *token = strtok(str, delim);
    
    while (token != NULL && count < max) {
        tokens[count++] = token;
        token = strtok(NULL, delim);
    }
    
    return count;
}

void example10_tokenizing(void) {
    printf("\n=== EXAMPLE 10: Tokenizing into String Array ===\n\n");
    
    char text[] = "apple,banana,cherry,date,elderberry";
    char *tokens[10];
    
    printf("Original: \"%s\"\n\n", text);
    
    int count = tokenize(text, tokens, 10, ",");
    
    printf("Tokenized by ',': %d tokens\n", count);
    for (int i = 0; i < count; i++) {
        printf("  tokens[%d] = \"%s\"\n", i, tokens[i]);
    }
    
    // Tokenize sentence
    printf("\n--- Tokenizing a sentence ---\n");
    char sentence[] = "The quick brown fox jumps over";
    char *words[20];
    
    count = tokenize(sentence, words, 20, " ");
    
    printf("Words: ");
    for (int i = 0; i < count; i++) {
        printf("\"%s\" ", words[i]);
    }
    printf("\n");
}


/* ============================================================
 * EXAMPLE 11: Filtering String Arrays
 * ============================================================ */

int filter_by_length(char **arr, int n, char **result, int min_len) {
    int count = 0;
    
    for (int i = 0; i < n; i++) {
        if (strlen(arr[i]) >= (size_t)min_len) {
            result[count++] = arr[i];
        }
    }
    
    return count;
}

int filter_by_prefix(char **arr, int n, char **result, const char *prefix) {
    int count = 0;
    size_t prefix_len = strlen(prefix);
    
    for (int i = 0; i < n; i++) {
        if (strncmp(arr[i], prefix, prefix_len) == 0) {
            result[count++] = arr[i];
        }
    }
    
    return count;
}

void example11_filtering(void) {
    printf("\n=== EXAMPLE 11: Filtering String Arrays ===\n\n");
    
    char *words[] = {"apple", "apricot", "banana", "blueberry", 
                     "cherry", "avocado", "kiwi"};
    int count = 7;
    char *filtered[10];
    
    printf("Original: ");
    for (int i = 0; i < count; i++) printf("%s ", words[i]);
    printf("\n\n");
    
    // Filter by minimum length
    printf("--- Filter: length >= 6 ---\n");
    int filtered_count = filter_by_length(words, count, filtered, 6);
    printf("Result: ");
    for (int i = 0; i < filtered_count; i++) printf("%s ", filtered[i]);
    printf("(%d matches)\n\n", filtered_count);
    
    // Filter by prefix
    printf("--- Filter: prefix \"a\" ---\n");
    filtered_count = filter_by_prefix(words, count, filtered, "a");
    printf("Result: ");
    for (int i = 0; i < filtered_count; i++) printf("%s ", filtered[i]);
    printf("(%d matches)\n", filtered_count);
}


/* ============================================================
 * EXAMPLE 12: Copying and Comparing String Arrays
 * ============================================================ */

char **copy_string_array(char **src, int count) {
    char **dest = malloc(count * sizeof(char *));
    if (dest == NULL) return NULL;
    
    for (int i = 0; i < count; i++) {
        dest[i] = strdup(src[i]);
        if (dest[i] == NULL) {
            // Cleanup on failure
            for (int j = 0; j < i; j++) {
                free(dest[j]);
            }
            free(dest);
            return NULL;
        }
    }
    
    return dest;
}

int arrays_equal(char **arr1, char **arr2, int count) {
    for (int i = 0; i < count; i++) {
        if (strcmp(arr1[i], arr2[i]) != 0) {
            return 0;
        }
    }
    return 1;
}

void example12_copy_compare(void) {
    printf("\n=== EXAMPLE 12: Copying and Comparing ===\n\n");
    
    char *original[] = {"one", "two", "three"};
    int count = 3;
    
    printf("Original array: ");
    for (int i = 0; i < count; i++) printf("%s ", original[i]);
    printf("\n");
    
    // Deep copy
    char **copy = copy_string_array(original, count);
    
    printf("Copied array:   ");
    for (int i = 0; i < count; i++) printf("%s ", copy[i]);
    printf("\n\n");
    
    // Compare
    printf("Arrays equal? %s\n", 
           arrays_equal(original, copy, count) ? "Yes" : "No");
    
    // Modify copy
    strcpy(copy[0], "ONE");
    printf("\nAfter modifying copy[0] to \"ONE\":\n");
    printf("Original: ");
    for (int i = 0; i < count; i++) printf("%s ", original[i]);
    printf("\n");
    printf("Copy:     ");
    for (int i = 0; i < count; i++) printf("%s ", copy[i]);
    printf("\n");
    
    printf("Arrays equal? %s\n", 
           arrays_equal(original, copy, count) ? "Yes" : "No");
    
    // Cleanup
    for (int i = 0; i < count; i++) {
        free(copy[i]);
    }
    free(copy);
}


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

int main(void) {
    printf("╔═══════════════════════════════════════════════════════╗\n");
    printf("ā•‘     STRING ARRAYS AND POINTERS - EXAMPLES             ā•‘\n");
    printf("ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n\n");
    
    example1_array_types();
    example2_memory_layout();
    example3_accessing();
    example4_dynamic_allocation();
    example5_strdup();
    example6_sorting();
    example7_searching();
    example8_command_line();
    example9_null_terminated();
    example10_tokenizing();
    example11_filtering();
    example12_copy_compare();
    
    printf("\n╔═══════════════════════════════════════════════════════╗\n");
    printf("ā•‘              ALL EXAMPLES COMPLETED!                  ā•‘\n");
    printf("ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•\n");
    
    return 0;
}
Examples - C Programming Tutorial | DeepML