c
exercises
exercises.c🔧c
/**
* String Functions - Exercises
*
* Practice problems for standard library string functions.
* Each exercise includes the problem statement and solution.
*
* Compile: gcc exercises.c -o exercises
* Run: ./exercises
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* ============================================================
* EXERCISE 1: Implement strcat
*
* Write a function that concatenates src to the end of dest.
* Return pointer to dest.
* ============================================================ */
char* exercise1_my_strcat(char *dest, const char *src) {
// YOUR CODE HERE
// Hints:
// - Find end of dest
// - Copy src characters there
// - Add null terminator
return dest;
}
// Solution
char* solution1_my_strcat(char *dest, const char *src) {
char *ptr = dest;
// Find end of dest
while (*ptr) {
ptr++;
}
// Copy src
while (*src) {
*ptr++ = *src++;
}
*ptr = '\0';
return dest;
}
void test_exercise1(void) {
printf("=== Exercise 1: Implement strcat ===\n\n");
char str1[30] = "Hello";
char str2[30] = "Hi";
solution1_my_strcat(str1, " World");
solution1_my_strcat(str2, "");
printf("Testing solution1_my_strcat:\n");
printf(" \"Hello\" + \" World\" = \"%s\"\n", str1);
printf(" \"Hi\" + \"\" = \"%s\"\n", str2);
printf("\n");
}
/* ============================================================
* EXERCISE 2: Implement strstr
*
* Write a function that finds the first occurrence of needle
* in haystack. Return pointer to match or NULL.
* ============================================================ */
char* exercise2_my_strstr(const char *haystack, const char *needle) {
// YOUR CODE HERE
// Hints:
// - Handle empty needle (return haystack)
// - For each position, try to match needle
return NULL;
}
// Solution
char* solution2_my_strstr(const char *haystack, const char *needle) {
if (*needle == '\0') {
return (char *)haystack;
}
while (*haystack) {
const char *h = haystack;
const char *n = needle;
// Try to match needle at current position
while (*h && *n && *h == *n) {
h++;
n++;
}
// Found complete match
if (*n == '\0') {
return (char *)haystack;
}
haystack++;
}
return NULL;
}
void test_exercise2(void) {
printf("=== Exercise 2: Implement strstr ===\n\n");
const char *text = "Hello World";
printf("String: \"%s\"\n\n", text);
printf("Testing solution2_my_strstr:\n");
char *result = solution2_my_strstr(text, "World");
printf(" Find \"World\": %s\n", result ? result : "NULL");
result = solution2_my_strstr(text, "lo");
printf(" Find \"lo\": %s\n", result ? result : "NULL");
result = solution2_my_strstr(text, "xyz");
printf(" Find \"xyz\": %s\n", result ? result : "NULL");
result = solution2_my_strstr(text, "");
printf(" Find \"\": %s\n", result ? result : "NULL");
printf("\n");
}
/* ============================================================
* EXERCISE 3: Count Substring Occurrences
*
* Write a function that counts how many times a substring
* appears in a string.
* ============================================================ */
int exercise3_count_substring(const char *str, const char *sub) {
// YOUR CODE HERE
// Hints:
// - Use strstr repeatedly
// - Move past each match to find next
return 0;
}
// Solution
int solution3_count_substring(const char *str, const char *sub) {
if (sub[0] == '\0') return 0;
int count = 0;
const char *ptr = str;
while ((ptr = strstr(ptr, sub)) != NULL) {
count++;
ptr++; // Move past this match
}
return count;
}
void test_exercise3(void) {
printf("=== Exercise 3: Count Substring ===\n\n");
printf("Testing solution3_count_substring:\n");
printf(" \"abababab\" contains \"ab\": %d times\n",
solution3_count_substring("abababab", "ab"));
printf(" \"hello\" contains \"l\": %d times\n",
solution3_count_substring("hello", "l"));
printf(" \"aaa\" contains \"aa\": %d times (overlapping)\n",
solution3_count_substring("aaa", "aa"));
printf(" \"hello\" contains \"xyz\": %d times\n",
solution3_count_substring("hello", "xyz"));
printf("\n");
}
/* ============================================================
* EXERCISE 4: Replace Character
*
* Write a function that replaces all occurrences of a character
* with another character (in place).
* ============================================================ */
void exercise4_replace_char(char *str, char old, char new) {
// YOUR CODE HERE
}
// Solution
void solution4_replace_char(char *str, char old_char, char new_char) {
while (*str) {
if (*str == old_char) {
*str = new_char;
}
str++;
}
}
void test_exercise4(void) {
printf("=== Exercise 4: Replace Character ===\n\n");
char str1[] = "hello world";
char str2[] = "mississippi";
solution4_replace_char(str1, ' ', '_');
solution4_replace_char(str2, 'i', 'o');
printf("Testing solution4_replace_char:\n");
printf(" \"hello world\" (' ' -> '_'): \"%s\"\n", str1);
printf(" \"mississippi\" ('i' -> 'o'): \"%s\"\n", str2);
printf("\n");
}
/* ============================================================
* EXERCISE 5: Trim Whitespace
*
* Write a function that removes leading and trailing whitespace
* from a string (in place). Return pointer to trimmed string.
* ============================================================ */
char* exercise5_trim(char *str) {
// YOUR CODE HERE
// Hints:
// - Use strspn to skip leading spaces
// - Find last non-space character
// - Use memmove if needed
return str;
}
// Solution
char* solution5_trim(char *str) {
// Skip leading whitespace
char *start = str;
while (isspace(*start)) {
start++;
}
// All spaces?
if (*start == '\0') {
*str = '\0';
return str;
}
// Find end of string
char *end = start + strlen(start) - 1;
// Skip trailing whitespace
while (end > start && isspace(*end)) {
end--;
}
// Null terminate
*(end + 1) = '\0';
// Move to beginning if needed
if (start != str) {
memmove(str, start, end - start + 2);
}
return str;
}
void test_exercise5(void) {
printf("=== Exercise 5: Trim Whitespace ===\n\n");
char str1[] = " Hello World ";
char str2[] = " ";
char str3[] = "NoSpaces";
char str4[] = " Leading";
printf("Testing solution5_trim:\n");
printf(" \" Hello World \" -> \"%s\"\n", solution5_trim(str1));
printf(" \" \" -> \"%s\"\n", solution5_trim(str2));
printf(" \"NoSpaces\" -> \"%s\"\n", solution5_trim(str3));
printf(" \" Leading\" -> \"%s\"\n", solution5_trim(str4));
printf("\n");
}
/* ============================================================
* EXERCISE 6: Split String into Words
*
* Write a function that counts words and prints each one.
* Use strtok.
* ============================================================ */
int exercise6_split_words(char *str) {
// YOUR CODE HERE
// Hints:
// - Use strtok with " \t\n" delimiters
// - Print each token and count
return 0;
}
// Solution
int solution6_split_words(char *str) {
int count = 0;
char *token = strtok(str, " \t\n");
while (token != NULL) {
count++;
printf(" Word %d: \"%s\"\n", count, token);
token = strtok(NULL, " \t\n");
}
return count;
}
void test_exercise6(void) {
printf("=== Exercise 6: Split into Words ===\n\n");
char str1[] = "Hello World How Are You";
char str2[] = " Multiple Spaces ";
printf("String: \"Hello World How Are You\"\n");
int count1 = solution6_split_words(str1);
printf(" Total words: %d\n\n", count1);
printf("String: \" Multiple Spaces \"\n");
int count2 = solution6_split_words(str2);
printf(" Total words: %d\n\n", count2);
}
/* ============================================================
* EXERCISE 7: Parse CSV Line
*
* Write a function that parses a CSV line into fields.
* Print each field.
* ============================================================ */
int exercise7_parse_csv(char *line) {
// YOUR CODE HERE
// Hint: Use strtok with "," delimiter
return 0;
}
// Solution
int solution7_parse_csv(char *line) {
int field = 0;
char *token = strtok(line, ",");
while (token != NULL) {
field++;
// Trim leading spaces
while (*token == ' ') token++;
printf(" Field %d: \"%s\"\n", field, token);
token = strtok(NULL, ",");
}
return field;
}
void test_exercise7(void) {
printf("=== Exercise 7: Parse CSV ===\n\n");
char csv1[] = "John,25,Engineer,NYC";
char csv2[] = "Alice, 30, Designer, LA";
printf("CSV: \"John,25,Engineer,NYC\"\n");
int count1 = solution7_parse_csv(csv1);
printf(" Total fields: %d\n\n", count1);
printf("CSV: \"Alice, 30, Designer, LA\"\n");
int count2 = solution7_parse_csv(csv2);
printf(" Total fields: %d\n\n", count2);
}
/* ============================================================
* EXERCISE 8: Safe String Copy
*
* Write a function that safely copies a string with size limit.
* Always null-terminates. Returns 0 if truncated.
* ============================================================ */
int exercise8_safe_strcpy(char *dest, size_t dest_size, const char *src) {
// YOUR CODE HERE
// Hints:
// - Use strncpy
// - Always null terminate
// - Return 1 if complete, 0 if truncated
return 1;
}
// Solution
int solution8_safe_strcpy(char *dest, size_t dest_size, const char *src) {
if (dest_size == 0) return 0;
size_t src_len = strlen(src);
if (src_len < dest_size) {
// Fits completely
strcpy(dest, src);
return 1;
} else {
// Truncated
strncpy(dest, src, dest_size - 1);
dest[dest_size - 1] = '\0';
return 0;
}
}
void test_exercise8(void) {
printf("=== Exercise 8: Safe String Copy ===\n\n");
char dest[10];
int result;
result = solution8_safe_strcpy(dest, sizeof(dest), "Hello");
printf("Copy \"Hello\" to buffer[10]: \"%s\" (truncated: %s)\n",
dest, result ? "No" : "Yes");
result = solution8_safe_strcpy(dest, sizeof(dest), "Hello World!!!");
printf("Copy \"Hello World!!!\" to buffer[10]: \"%s\" (truncated: %s)\n",
dest, result ? "No" : "Yes");
printf("\n");
}
/* ============================================================
* EXERCISE 9: Find and Replace Substring
*
* Write a function that replaces the first occurrence of a
* substring with another string. Assume dest has enough space.
* ============================================================ */
int exercise9_replace_first(char *str, size_t size,
const char *old_sub, const char *new_sub) {
// YOUR CODE HERE
// Hints:
// - Find old_sub with strstr
// - Use memmove to make space/remove space
// - Copy new_sub in place
return 0;
}
// Solution
int solution9_replace_first(char *str, size_t size,
const char *old_sub, const char *new_sub) {
char *pos = strstr(str, old_sub);
if (pos == NULL) return 0;
size_t old_len = strlen(old_sub);
size_t new_len = strlen(new_sub);
size_t str_len = strlen(str);
size_t tail_len = strlen(pos + old_len);
// Check if result fits
if (str_len - old_len + new_len >= size) {
return 0; // Won't fit
}
// Move the tail
memmove(pos + new_len, pos + old_len, tail_len + 1);
// Copy new substring
memcpy(pos, new_sub, new_len);
return 1;
}
void test_exercise9(void) {
printf("=== Exercise 9: Replace Substring ===\n\n");
char str1[50] = "Hello World";
char str2[50] = "The quick brown fox";
char str3[50] = "aaa bbb aaa";
solution9_replace_first(str1, sizeof(str1), "World", "Everyone");
solution9_replace_first(str2, sizeof(str2), "quick", "slow");
solution9_replace_first(str3, sizeof(str3), "aaa", "XXX");
printf("Testing solution9_replace_first:\n");
printf(" \"Hello World\" -> \"Hello Everyone\": \"%s\"\n", str1);
printf(" \"The quick brown fox\" -> \"The slow brown fox\": \"%s\"\n", str2);
printf(" \"aaa bbb aaa\" (replace first aaa): \"%s\"\n", str3);
printf("\n");
}
/* ============================================================
* EXERCISE 10: Extract Filename from Path
*
* Write a function that extracts the filename from a file path.
* Example: "/home/user/file.txt" -> "file.txt"
* ============================================================ */
const char* exercise10_get_filename(const char *path) {
// YOUR CODE HERE
// Hints:
// - Use strrchr to find last '/' or '\\'
// - Return pointer after the separator
return path;
}
// Solution
const char* solution10_get_filename(const char *path) {
// Check for Unix-style separator
const char *slash = strrchr(path, '/');
// Check for Windows-style separator
const char *backslash = strrchr(path, '\\');
// Use whichever comes last
const char *last_sep = NULL;
if (slash && backslash) {
last_sep = (slash > backslash) ? slash : backslash;
} else if (slash) {
last_sep = slash;
} else if (backslash) {
last_sep = backslash;
}
if (last_sep) {
return last_sep + 1;
}
return path; // No separator found
}
void test_exercise10(void) {
printf("=== Exercise 10: Extract Filename ===\n\n");
printf("Testing solution10_get_filename:\n");
printf(" \"/home/user/file.txt\" -> \"%s\"\n",
solution10_get_filename("/home/user/file.txt"));
printf(" \"C:\\\\Users\\\\file.txt\" -> \"%s\"\n",
solution10_get_filename("C:\\Users\\file.txt"));
printf(" \"file.txt\" -> \"%s\"\n",
solution10_get_filename("file.txt"));
printf(" \"/path/to/dir/\" -> \"%s\"\n",
solution10_get_filename("/path/to/dir/"));
printf("\n");
}
/* ============================================================
* ANSWER KEY SUMMARY
* ============================================================ */
void print_answer_key(void) {
printf("\n");
printf("╔═══════════════════════════════════════════════════════════════╗\n");
printf("║ STRING FUNCTIONS - ANSWER KEY ║\n");
printf("╚═══════════════════════════════════════════════════════════════╝\n\n");
printf("Exercise 1: Implement strcat\n");
printf("─────────────────────────────────────────\n");
printf(" Find end of dest, then copy src\n\n");
printf("Exercise 2: Implement strstr\n");
printf("─────────────────────────────────────────\n");
printf(" For each position, try matching needle\n");
printf(" Return position if complete match\n\n");
printf("Exercise 3: Count Substring\n");
printf("─────────────────────────────────────────\n");
printf(" Use strstr repeatedly, move past each match\n\n");
printf("Exercise 4: Replace Character\n");
printf("─────────────────────────────────────────\n");
printf(" Loop through, replace if match\n\n");
printf("Exercise 5: Trim Whitespace\n");
printf("─────────────────────────────────────────\n");
printf(" Skip leading with isspace\n");
printf(" Find last non-space, null terminate\n");
printf(" memmove if start moved\n\n");
printf("Exercise 6: Split into Words\n");
printf("─────────────────────────────────────────\n");
printf(" Use strtok with space delimiters\n");
printf(" First call: pass string\n");
printf(" Subsequent: pass NULL\n\n");
printf("Exercise 7: Parse CSV\n");
printf("─────────────────────────────────────────\n");
printf(" Use strtok with comma delimiter\n");
printf(" Trim leading spaces from each field\n\n");
printf("Exercise 8: Safe String Copy\n");
printf("─────────────────────────────────────────\n");
printf(" Check if fits, use strncpy\n");
printf(" Always null-terminate dest[size-1]\n\n");
printf("Exercise 9: Replace Substring\n");
printf("─────────────────────────────────────────\n");
printf(" Find with strstr\n");
printf(" memmove tail to make room\n");
printf(" memcpy new substring\n\n");
printf("Exercise 10: Extract Filename\n");
printf("─────────────────────────────────────────\n");
printf(" Use strrchr to find last / or \\\\\n");
printf(" Return pointer after separator\n\n");
printf("═══════════════════════════════════════════════════════════════\n");
printf("KEY STRING FUNCTIONS:\n");
printf("═══════════════════════════════════════════════════════════════\n");
printf("• strlen(s) - String length\n");
printf("• strcpy(d,s) - Copy string\n");
printf("• strcat(d,s) - Concatenate strings\n");
printf("• strcmp(s1,s2) - Compare strings\n");
printf("• strchr(s,c) - Find character\n");
printf("• strrchr(s,c) - Find last character\n");
printf("• strstr(hay,needle) - Find substring\n");
printf("• strtok(s,delim) - Tokenize string\n");
printf("• memcpy(d,s,n) - Copy memory\n");
printf("• memmove(d,s,n) - Safe memory copy\n");
printf("═══════════════════════════════════════════════════════════════\n");
}
/* ============================================================
* MAIN FUNCTION
* ============================================================ */
int main() {
printf("╔═══════════════════════════════════════════════════════════════╗\n");
printf("║ STRING FUNCTIONS - EXERCISES ║\n");
printf("╚═══════════════════════════════════════════════════════════════╝\n\n");
test_exercise1();
test_exercise2();
test_exercise3();
test_exercise4();
test_exercise5();
test_exercise6();
test_exercise7();
test_exercise8();
test_exercise9();
test_exercise10();
print_answer_key();
return 0;
}