c
exercises
exercises.c🔧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.
*
* ============================================================ */