c

exercises

exercises.c🔧
/**
 * String Arrays and Pointers - Exercises
 * 
 * Practice problems for working with arrays of strings in C.
 * Each exercise includes hints and a solution in the answer key.
 * 
 * Compile: gcc exercises.c -o exercises
 * Run: ./exercises
 */

#define _POSIX_C_SOURCE 200809L  // For strdup

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

/* ============================================================
 * EXERCISE 1: Find Longest String
 * 
 * Write a function find_longest that finds the longest string
 * in an array and returns its index. If there are ties, return
 * the first one.
 * 
 * Example:
 *   {"apple", "banana", "cherry", "kiwi"} -> 2 ("cherry", len 6)
 * 
 * Hints:
 * - Track maximum length and its index
 * - Use strlen() to get each string's length
 * - Return the index, not the string
 * ============================================================ */

int find_longest(char **arr, int count) {
    // YOUR CODE HERE
    return -1;
}

void test_exercise1(void) {
    printf("=== Exercise 1: Find Longest String ===\n");
    
    char *fruits[] = {"apple", "banana", "cherry", "kiwi"};
    int idx = find_longest(fruits, 4);
    printf("Array: apple, banana, cherry, kiwi\n");
    printf("Longest at index: %d (Expected: 2, \"cherry\")\n", idx);
    if (idx >= 0 && idx < 4) {
        printf("String: \"%s\"\n\n", fruits[idx]);
    }
    
    char *words[] = {"a", "bb", "ccc", "dd"};
    idx = find_longest(words, 4);
    printf("Array: a, bb, ccc, dd\n");
    printf("Longest at index: %d (Expected: 2, \"ccc\")\n\n", idx);
}


/* ============================================================
 * EXERCISE 2: Count Strings Starting With
 * 
 * Write a function count_starting_with that counts how many
 * strings in an array start with a given character (case-
 * insensitive).
 * 
 * Example:
 *   {"Apple", "apricot", "Banana"}, 'a' -> 2
 * 
 * Hints:
 * - Use tolower() for case-insensitive comparison
 * - Check first character of each string
 * ============================================================ */

int count_starting_with(char **arr, int count, char c) {
    // YOUR CODE HERE
    return 0;
}

void test_exercise2(void) {
    printf("=== Exercise 2: Count Strings Starting With ===\n");
    
    char *fruits[] = {"Apple", "apricot", "Banana", "avocado", "blueberry"};
    
    printf("Array: Apple, apricot, Banana, avocado, blueberry\n");
    printf("Starting with 'a': %d (Expected: 3)\n", 
           count_starting_with(fruits, 5, 'a'));
    printf("Starting with 'b': %d (Expected: 2)\n", 
           count_starting_with(fruits, 5, 'b'));
    printf("Starting with 'c': %d (Expected: 0)\n\n", 
           count_starting_with(fruits, 5, 'c'));
}


/* ============================================================
 * EXERCISE 3: Reverse String Array
 * 
 * Write a function reverse_array that reverses the order of
 * strings in an array (not the strings themselves).
 * 
 * Example:
 *   {"one", "two", "three"} -> {"three", "two", "one"}
 * 
 * Hints:
 * - Swap pointers from both ends
 * - Only need to go halfway through the array
 * ============================================================ */

void reverse_array(char **arr, int count) {
    // YOUR CODE HERE
    
}

void test_exercise3(void) {
    printf("=== Exercise 3: Reverse String Array ===\n");
    
    char *words[] = {"one", "two", "three", "four", "five"};
    int count = 5;
    
    printf("Before: ");
    for (int i = 0; i < count; i++) printf("%s ", words[i]);
    printf("\n");
    
    reverse_array(words, count);
    
    printf("After:  ");
    for (int i = 0; i < count; i++) printf("%s ", words[i]);
    printf("\n");
    printf("Expected: five four three two one\n\n");
}


/* ============================================================
 * EXERCISE 4: Remove Duplicates
 * 
 * Write a function remove_duplicates that removes duplicate
 * strings from an array (keep first occurrence). Return the
 * new count.
 * 
 * Example:
 *   {"apple", "banana", "apple", "cherry", "banana"}
 *   -> {"apple", "banana", "cherry"}, returns 3
 * 
 * Hints:
 * - Use strcmp to compare strings
 * - Track unique strings count
 * - Shift remaining elements
 * ============================================================ */

int remove_duplicates(char **arr, int count) {
    // YOUR CODE HERE
    return count;
}

void test_exercise4(void) {
    printf("=== Exercise 4: Remove Duplicates ===\n");
    
    char *words[] = {"apple", "banana", "apple", "cherry", "banana", "date"};
    int count = 6;
    
    printf("Before: ");
    for (int i = 0; i < count; i++) printf("%s ", words[i]);
    printf("(count: %d)\n", count);
    
    count = remove_duplicates(words, count);
    
    printf("After:  ");
    for (int i = 0; i < count; i++) printf("%s ", words[i]);
    printf("(count: %d)\n", count);
    printf("Expected: apple banana cherry date (count: 4)\n\n");
}


/* ============================================================
 * EXERCISE 5: Join with Separator
 * 
 * Write a function join_strings that joins all strings in an
 * array with a separator, storing the result in a buffer.
 * 
 * Example:
 *   {"Hello", "World"}, ", " -> "Hello, World"
 * 
 * Hints:
 * - Build result incrementally
 * - Add separator between strings (not after last)
 * - Make sure result fits in buffer
 * ============================================================ */

void join_strings(char **arr, int count, const char *sep, 
                  char *result, size_t size) {
    // YOUR CODE HERE
    
}

void test_exercise5(void) {
    printf("=== Exercise 5: Join with Separator ===\n");
    
    char *words[] = {"apple", "banana", "cherry"};
    char result[100];
    
    join_strings(words, 3, ", ", result, sizeof(result));
    printf("Join with \", \": \"%s\"\n", result);
    printf("Expected: \"apple, banana, cherry\"\n\n");
    
    join_strings(words, 3, " -> ", result, sizeof(result));
    printf("Join with \" -> \": \"%s\"\n", result);
    printf("Expected: \"apple -> banana -> cherry\"\n\n");
    
    char *single[] = {"only"};
    join_strings(single, 1, ", ", result, sizeof(result));
    printf("Single element: \"%s\"\n", result);
    printf("Expected: \"only\"\n\n");
}


/* ============================================================
 * EXERCISE 6: Find Common Prefix
 * 
 * Write a function common_prefix that finds the longest common
 * prefix among all strings in an array.
 * 
 * Example:
 *   {"flower", "flow", "flight"} -> "fl"
 *   {"dog", "car", "race"} -> "" (empty)
 * 
 * Hints:
 * - Compare character by character
 * - Use first string as reference
 * - Stop at first mismatch in any string
 * ============================================================ */

void common_prefix(char **arr, int count, char *result) {
    // YOUR CODE HERE
    
}

void test_exercise6(void) {
    printf("=== Exercise 6: Find Common Prefix ===\n");
    
    char result[100];
    
    char *words1[] = {"flower", "flow", "flight"};
    common_prefix(words1, 3, result);
    printf("flower, flow, flight -> \"%s\" (Expected: \"fl\")\n", result);
    
    char *words2[] = {"interspecies", "interstellar", "interstate"};
    common_prefix(words2, 3, result);
    printf("interspecies, interstellar, interstate -> \"%s\" (Expected: \"inters\")\n", result);
    
    char *words3[] = {"dog", "car", "race"};
    common_prefix(words3, 3, result);
    printf("dog, car, race -> \"%s\" (Expected: \"\")\n\n", result);
}


/* ============================================================
 * EXERCISE 7: Sort by Length
 * 
 * Write a function sort_by_length that sorts strings by their
 * length in ascending order. For strings of equal length,
 * maintain original relative order (stable sort not required).
 * 
 * Example:
 *   {"medium", "a", "longer", "bb"} -> {"a", "bb", "medium", "longer"}
 * 
 * Hints:
 * - Compare strlen() values
 * - Use bubble sort with pointer swapping
 * ============================================================ */

void sort_by_length(char **arr, int count) {
    // YOUR CODE HERE
    
}

void test_exercise7(void) {
    printf("=== Exercise 7: Sort by Length ===\n");
    
    char *words[] = {"medium", "a", "longer", "bb", "xyz"};
    int count = 5;
    
    printf("Before: ");
    for (int i = 0; i < count; i++) printf("%s ", words[i]);
    printf("\n");
    
    sort_by_length(words, count);
    
    printf("After:  ");
    for (int i = 0; i < count; i++) printf("%s ", words[i]);
    printf("\n");
    printf("Expected (by length): a bb xyz medium longer\n\n");
}


/* ============================================================
 * EXERCISE 8: Rotate Array
 * 
 * Write a function rotate_left that rotates strings in an
 * array to the left by n positions.
 * 
 * Example (rotate left by 2):
 *   {"a", "b", "c", "d", "e"} -> {"c", "d", "e", "a", "b"}
 * 
 * Hints:
 * - Handle rotation count larger than array size
 * - You can use a temporary array or do it in-place
 * ============================================================ */

void rotate_left(char **arr, int count, int positions) {
    // YOUR CODE HERE
    
}

void test_exercise8(void) {
    printf("=== Exercise 8: Rotate Array ===\n");
    
    char *letters[] = {"a", "b", "c", "d", "e"};
    int count = 5;
    
    printf("Original: ");
    for (int i = 0; i < count; i++) printf("%s ", letters[i]);
    printf("\n");
    
    rotate_left(letters, count, 2);
    
    printf("Rotate 2: ");
    for (int i = 0; i < count; i++) printf("%s ", letters[i]);
    printf("\n");
    printf("Expected: c d e a b\n\n");
}


/* ============================================================
 * EXERCISE 9: Find All Occurrences
 * 
 * Write a function find_all that finds all indices where a
 * target string appears in an array. Return the count and
 * store indices in the result array.
 * 
 * Example:
 *   {"a", "b", "a", "c", "a"}, "a" -> indices [0, 2, 4], count 3
 * 
 * Hints:
 * - Use strcmp for comparison
 * - Store matching indices in result array
 * - Return count of matches
 * ============================================================ */

int find_all(char **arr, int count, const char *target, int *indices) {
    // YOUR CODE HERE
    return 0;
}

void test_exercise9(void) {
    printf("=== Exercise 9: Find All Occurrences ===\n");
    
    char *words[] = {"apple", "banana", "apple", "cherry", "apple"};
    int indices[10];
    
    int found = find_all(words, 5, "apple", indices);
    
    printf("Array: apple, banana, apple, cherry, apple\n");
    printf("Find \"apple\": %d occurrences at indices: ", found);
    for (int i = 0; i < found; i++) printf("%d ", indices[i]);
    printf("\n");
    printf("Expected: 3 occurrences at indices: 0 2 4\n\n");
    
    found = find_all(words, 5, "grape", indices);
    printf("Find \"grape\": %d occurrences\n", found);
    printf("Expected: 0 occurrences\n\n");
}


/* ============================================================
 * EXERCISE 10: Create Uppercase Copy
 * 
 * Write a function create_uppercase_array that creates a new
 * dynamically allocated array containing uppercase copies of
 * all strings in the input array.
 * 
 * Example:
 *   {"hello", "World"} -> {"HELLO", "WORLD"} (new array)
 * 
 * Requirements:
 * - Allocate new array and new strings
 * - Caller must free the returned array
 * - Return NULL on allocation failure
 * 
 * Hints:
 * - Use malloc for array of pointers
 * - Use strdup then uppercase in place
 * - Handle cleanup on failure
 * ============================================================ */

char **create_uppercase_array(char **arr, int count) {
    // YOUR CODE HERE
    return NULL;
}

void test_exercise10(void) {
    printf("=== Exercise 10: Create Uppercase Copy ===\n");
    
    char *words[] = {"hello", "World", "C Programming"};
    int count = 3;
    
    printf("Original: ");
    for (int i = 0; i < count; i++) printf("\"%s\" ", words[i]);
    printf("\n");
    
    char **upper = create_uppercase_array(words, count);
    
    if (upper != NULL) {
        printf("Uppercase: ");
        for (int i = 0; i < count; i++) printf("\"%s\" ", upper[i]);
        printf("\n");
        printf("Expected: \"HELLO\" \"WORLD\" \"C PROGRAMMING\"\n\n");
        
        // Original unchanged?
        printf("Original unchanged? ");
        for (int i = 0; i < count; i++) printf("\"%s\" ", words[i]);
        printf("\n");
        
        // Cleanup
        for (int i = 0; i < count; i++) {
            free(upper[i]);
        }
        free(upper);
    } else {
        printf("Allocation failed!\n\n");
    }
}


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

int main(void) {
    printf("╔═══════════════════════════════════════════════════════╗\n");
    printf("║      STRING ARRAYS AND POINTERS - EXERCISES           ║\n");
    printf("╚═══════════════════════════════════════════════════════╝\n\n");
    
    printf("Instructions:\n");
    printf("1. Implement each function marked with YOUR CODE HERE\n");
    printf("2. Compile and run to test your solutions\n");
    printf("3. Compare your output with expected results\n");
    printf("4. Check the answer key at the bottom for solutions\n\n");
    printf("═══════════════════════════════════════════════════════════\n\n");
    
    test_exercise1();
    test_exercise2();
    test_exercise3();
    test_exercise4();
    test_exercise5();
    test_exercise6();
    test_exercise7();
    test_exercise8();
    test_exercise9();
    test_exercise10();
    
    printf("═══════════════════════════════════════════════════════════\n");
    printf("Review the Answer Key below for solutions.\n");
    printf("═══════════════════════════════════════════════════════════\n\n");
    
    return 0;
}


/* ============================================================
 * ANSWER KEY
 * ============================================================ */

/*
 * EXERCISE 1 SOLUTION: Find Longest String
 * 
 * int find_longest(char **arr, int count) {
 *     if (count == 0) return -1;
 *     
 *     int max_idx = 0;
 *     size_t max_len = strlen(arr[0]);
 *     
 *     for (int i = 1; i < count; i++) {
 *         size_t len = strlen(arr[i]);
 *         if (len > max_len) {
 *             max_len = len;
 *             max_idx = i;
 *         }
 *     }
 *     
 *     return max_idx;
 * }
 */

/*
 * EXERCISE 2 SOLUTION: Count Strings Starting With
 * 
 * int count_starting_with(char **arr, int count, char c) {
 *     int result = 0;
 *     char target = tolower(c);
 *     
 *     for (int i = 0; i < count; i++) {
 *         if (arr[i][0] != '\0' && tolower(arr[i][0]) == target) {
 *             result++;
 *         }
 *     }
 *     
 *     return result;
 * }
 */

/*
 * EXERCISE 3 SOLUTION: Reverse String Array
 * 
 * void reverse_array(char **arr, int count) {
 *     int left = 0, right = count - 1;
 *     
 *     while (left < right) {
 *         char *temp = arr[left];
 *         arr[left] = arr[right];
 *         arr[right] = temp;
 *         left++;
 *         right--;
 *     }
 * }
 */

/*
 * EXERCISE 4 SOLUTION: Remove Duplicates
 * 
 * int remove_duplicates(char **arr, int count) {
 *     if (count <= 1) return count;
 *     
 *     int unique = 1;  // First element is always unique
 *     
 *     for (int i = 1; i < count; i++) {
 *         int is_dup = 0;
 *         for (int j = 0; j < unique; j++) {
 *             if (strcmp(arr[i], arr[j]) == 0) {
 *                 is_dup = 1;
 *                 break;
 *             }
 *         }
 *         if (!is_dup) {
 *             arr[unique++] = arr[i];
 *         }
 *     }
 *     
 *     return unique;
 * }
 */

/*
 * EXERCISE 5 SOLUTION: Join with Separator
 * 
 * void join_strings(char **arr, int count, const char *sep, 
 *                   char *result, size_t size) {
 *     result[0] = '\0';
 *     
 *     for (int i = 0; i < count; i++) {
 *         if (i > 0) {
 *             strncat(result, sep, size - strlen(result) - 1);
 *         }
 *         strncat(result, arr[i], size - strlen(result) - 1);
 *     }
 * }
 */

/*
 * EXERCISE 6 SOLUTION: Find Common Prefix
 * 
 * void common_prefix(char **arr, int count, char *result) {
 *     result[0] = '\0';
 *     
 *     if (count == 0) return;
 *     
 *     int idx = 0;
 *     while (arr[0][idx] != '\0') {
 *         char c = arr[0][idx];
 *         int all_match = 1;
 *         
 *         for (int i = 1; i < count; i++) {
 *             if (arr[i][idx] != c) {
 *                 all_match = 0;
 *                 break;
 *             }
 *         }
 *         
 *         if (all_match) {
 *             result[idx] = c;
 *             result[idx + 1] = '\0';
 *             idx++;
 *         } else {
 *             break;
 *         }
 *     }
 * }
 */

/*
 * EXERCISE 7 SOLUTION: Sort by Length
 * 
 * void sort_by_length(char **arr, int count) {
 *     for (int i = 0; i < count - 1; i++) {
 *         for (int j = 0; j < count - i - 1; j++) {
 *             if (strlen(arr[j]) > strlen(arr[j + 1])) {
 *                 char *temp = arr[j];
 *                 arr[j] = arr[j + 1];
 *                 arr[j + 1] = temp;
 *             }
 *         }
 *     }
 * }
 */

/*
 * EXERCISE 8 SOLUTION: Rotate Array
 * 
 * void rotate_left(char **arr, int count, int positions) {
 *     if (count == 0) return;
 *     
 *     positions = positions % count;  // Handle large rotations
 *     if (positions == 0) return;
 *     
 *     // Use temporary array
 *     char **temp = malloc(positions * sizeof(char *));
 *     
 *     // Save first 'positions' elements
 *     for (int i = 0; i < positions; i++) {
 *         temp[i] = arr[i];
 *     }
 *     
 *     // Shift remaining left
 *     for (int i = 0; i < count - positions; i++) {
 *         arr[i] = arr[i + positions];
 *     }
 *     
 *     // Place saved elements at end
 *     for (int i = 0; i < positions; i++) {
 *         arr[count - positions + i] = temp[i];
 *     }
 *     
 *     free(temp);
 * }
 */

/*
 * EXERCISE 9 SOLUTION: Find All Occurrences
 * 
 * int find_all(char **arr, int count, const char *target, int *indices) {
 *     int found = 0;
 *     
 *     for (int i = 0; i < count; i++) {
 *         if (strcmp(arr[i], target) == 0) {
 *             indices[found++] = i;
 *         }
 *     }
 *     
 *     return found;
 * }
 */

/*
 * EXERCISE 10 SOLUTION: Create Uppercase Copy
 * 
 * char **create_uppercase_array(char **arr, int count) {
 *     char **result = malloc(count * sizeof(char *));
 *     if (result == NULL) return NULL;
 *     
 *     for (int i = 0; i < count; i++) {
 *         result[i] = strdup(arr[i]);
 *         if (result[i] == NULL) {
 *             // Cleanup on failure
 *             for (int j = 0; j < i; j++) {
 *                 free(result[j]);
 *             }
 *             free(result);
 *             return NULL;
 *         }
 *         
 *         // Convert to uppercase
 *         for (char *p = result[i]; *p; p++) {
 *             *p = toupper(*p);
 *         }
 *     }
 *     
 *     return result;
 * }
 */


/* ============================================================
 * BONUS CHALLENGES
 * ============================================================
 * 
 * 1. Implement a function to merge two sorted string arrays
 *    into a single sorted array.
 * 
 * 2. Write a function that finds pairs of anagrams in an
 *    array of strings.
 * 
 * 3. Implement a function to group strings by their first
 *    letter (return array of arrays).
 * 
 * 4. Write a function that finds the most common string
 *    in an array.
 * 
 * 5. Implement a simple command-line argument parser that
 *    handles -flag and --option=value formats.
 * 
 * ============================================================ */
Exercises - C Programming Tutorial | DeepML