Once you have mastered the basics of C programming and completed our 9 topic-specific C programming exercises, it’s time to move on to more complex problems that bridge the gap between writing code and engineering software.
This comprehensive guide provides 45+ Intermediate C programming practice problems designed specifically for Intermediate developers.
Each coding exercise follows a structured format: a clear Practice Problem, the Given Input to get you started, a Hint to nudge your logic, and a Fully Explained Solution to ensure you understand the why behind the how.
Also, See: C Programming Exercises with 10 topic-wise sets and 320+ practice questions.
What You’ll Practice
These challenges focus on:
- General Intermediate coding questions
- Memory Manipulation: Using pointers and
malloc/freecorrectly. - Data Structures: Implementing linked lists, stacks, and queues from scratch.
- Algorithm Logic: Sorting, searching, and pattern-based problem solving.
- File I/O: Reading and writing structured and binary data to the disk.
Use Online C Compiler to solve exercises.
+ Table Of Contents (45 Exercises)
Table of contents
- Exercise 1: Swap by Reference
- Exercise 2: Dynamic Array Allocation
- Exercise 3: Find Max with Pointers
- Exercise 4: Array of Pointers (String Sorting)
- Exercise 5: Realloc Growth (Dynamic Sizing)
- Exercise 6: Function Pointers (Operation Selection)
- Exercise 7: Custom strlen with Pointer Subtraction
- Exercise 8: String Reversal In-Place
- Exercise 9: Anagram Checker (Frequency Array)
- Exercise 10: Palindrome Checker (Two-Pointer Method)
- Exercise 11: Word Counter
- Exercise 12: Student Database (Struct Arrays)
- Exercise 13: Complex Number Arithmetic (Returning Structs)
- Exercise 14: Time Difference (Normalization)
- Exercise 15: Nested Structs (Composition)
- Exercise 16: Unions vs. Structs (Memory Sharing)
- Exercise 17: File Copy (Character Stream)
- Exercise 18: Line Counter
- Exercise 19: Binary Struct Storage
- Exercise 20: Singly Linked List (Insertion at Head)
- Exercise 21: Linked List Search
- Exercise 22: Stack (Array-based)
- Exercise 23: Queue (Enqueue Operation)
- Exercise 24: Delete Node by Value
- Exercise 25: Binary Search
- Exercise 26: Bubble Sort vs Selection Sort
- Exercise 27: Bitwise Toggle
- Exercise 28: Decimal to Binary (Bitmasking)
- Exercise 29: Sorting Structure Data
- Exercise 30: Second Largest Element in an Array
- Exercise 31: Merge Two Sorted Arrays
- Exercise 32: Remove Duplicate Elements
- Exercise 33: Most Frequent Character
- Exercise 34: Fibonacci Series (Recursion)
- Exercise 35: Intersection of Two Arrays
- Exercise 36: Move Zeros to the End
- Exercise 37: Sort Strings Alphabetically (Pointers)
- Exercise 38: Longest Word in a Sentence
- Exercise 39: Pascal’s Triangle
- Exercise 40: Hollow Triangle Pattern
- Exercise 41: Solid Diamond Pattern
- Exercise 42: Alternating Positive and Negative Order
- Exercise 43: File Stats (Lines, Words, Characters)
- Exercise 44: Middle Element of a Linked List
Exercise 1: Swap by Reference
Practice Problem: Write a function swap(int *a, int *b) that takes the addresses of two integers and swaps their values.
Exercise Purpose: This is the foundation of pointer-based manipulation. It teaches how C uses “Pass by Reference” via pointers to allow a function to change variables located in a different scope (like main).
Given Input: int x = 10, y = 20
Expected Output:
Before Swap: x = 10, y = 20
After Swap: x = 20, y = 10
+ Hint
Use a temporary integer variable inside the function to store the value of *a before you overwrite it with the value of *b.
+ Show Solution
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a; // Store value at address a
*a = *b; // Put value from b into address a
*b = temp; // Put stored value into address b
}
int main() {
int x = 10, y = 20;
printf("Before Swap: x = %d, y = %d\n", x, y);
swap(&x, &y); // Passing addresses of x and y
printf("After Swap: x = %d, y = %d\n", x, y);
return 0;
}Code language: C++ (cpp)
Explanation:
swap(&x, &y): The&operator sends the memory addresses ofxandyto the function.int temp = *a: The*(dereference) operator looks inside the memory addressato get the actual number (10) and saves it intemp.*a = *b: This directly changes the memory at addressato whatever is currently sitting at addressb.
Exercise 2: Dynamic Array Allocation
Practice Problem: Write a C++ program for a size N, allocates an integer array of that size using malloc, and fills it with values. Print the memory address of the array to show it is located on the Heap, then free the memory.
Exercise Purpose: Static arrays have a fixed size at compile-time. This exercise introduces Dynamic Memory Allocation, allowing your program to request exactly as much memory as it needs while it is running.
Given Input:
- Array Size:
3 - Values:
100, 200, 300
Expected Output:
Array allocated at Heap Address: 0x5f5579932910
Value at index 0: 100
Value at index 1: 200
Value at index 2: 300
Memory successfully freed.
+ Hint
- Remember to include
<stdlib.h>formallocand always callfree()at the end of your program. mallocreturns avoid*, so you should cast it to(int*). The total bytes requested should besize * sizeof(int).
+ Show Solution
#include <stdio.h>
#include <stdlib.h>
int main() {
int n = 3;
int *arr = (int*)malloc(n * sizeof(int));
if (arr == NULL) return 1; // Check if allocation failed
printf("Array allocated at Heap Address: %p\n", (void*)arr);
for (int i = 0; i < n; i++) {
arr[i] = (i + 1) * 100;
printf("Value at index %d: %d\n", i, arr[i]);
}
free(arr); // Clean up
printf("Memory successfully freed.\n");
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
Static arrays require a size known at compile-time.
malloc(n * sizeof(int)): Requests a block of bytes from the Heap. Since anintis usually 4 bytes, this requests 12 bytes for 3 integers.if (arr == NULL): This is a safety check. If the computer is out of RAM,mallocreturnsNULL, and attempting to write to it would crash the program.free(arr): This tells the Operating System that the 12 bytes are no longer needed. If you skip this in a large program, you create a “Memory Leak.”
Exercise 3: Find Max with Pointers
Practice Problem: Write a function that accepts an array and its size, then returns a pointer to the maximum element in that array. Print the value and the index of the max element using that pointer.
Exercise Purpose: This demonstrates that pointers can be used not just to point to variables, but to navigate through array elements using pointer arithmetic.
Given Input: Array: {12, 45, 7, 99, 23}
Expected Output:
Searching array: 12, 45, 7, 99, 23
Max Value: 99 found at Index: 3
+ Hint
Instead of returning an integer, return int*. Inside the function, compare the value at the current pointer address with the value at the max pointer address.
+ Show Solution
#include <stdio.h>
int* find_max(int *arr, int size) {
int *max_ptr = arr;
for (int i = 1; i < size; i++) {
if (*(arr + i) > *max_ptr) {
max_ptr = arr + i;
}
}
return max_ptr;
}
int main() {
int nums[] = {12, 45, 7, 99, 23};
int *max = find_max(nums, 5);
printf("Max value: %d\n", *max);
return 0;
}Code language: C++ (cpp)
Explanation:
max_ptr = arr + i:arris the address of index 0.arr + iuses pointer arithmetic to calculate the memory address of indexi.*(arr + i): The*dereferences the calculated address to get the number stored there for comparison.max - nums: Subtracting the base address of the array (nums) from the pointer to an element (max) gives the number of elements between them, which is the index.
This approach is widely used in C to allow the caller to not only read the maximum value but also modify it directly at its source memory location if needed.
Exercise 4: Array of Pointers (String Sorting)
Practice Problem: Create an array of 3 strings (char pointers). Write a program to swap the pointers to “sort” the strings based on their length.
Given:
const char *list[] = {"Watermelon", "Apple", "Banana"};Code language: C++ (cpp)
Expected Output:
Shortest: Apple, Longest: Watermelon
+ Hint
You aren’t swapping the characters inside the strings; you are just swapping the memory addresses stored in the pointer array.
+ Show Solution
#include <stdio.h>
#include <string.h>
int main() {
char *list[] = {"Watermelon", "Apple", "Banana"};
for (int i = 0; i < 2; i++) {
if (strlen(list[i]) > strlen(list[i+1])) {
char *temp = list[i];
list[i] = list[i+1];
list[i+1] = temp;
}
}
printf("Shortest: %s, Longest: %s\n", list[0], list[1]);
return 0;
}Code language: C++ (cpp)
Explanation:
An array of pointers treats strings as independent blocks of memory. Swapping two pointers is a constant-time operation (O(1)), which is significantly faster than using strcpy to move every character of a long string.
This technique is the backbone of efficient sorting algorithms in C, where we move small “handles” (pointers) to the data rather than moving the bulky data itself.
Exercise 5: Realloc Growth (Dynamic Sizing)
Practice Problem: Create a dynamic array with an initial capacity of 2. Add numbers to it, and when the capacity is reached, use realloc to double the size. Stop when 5 numbers are added and print the final capacity.
Exercise Purpose: This shows how the realloc function handles memory. If there isn’t enough space to expand the current block, it finds a new home for your data, copies it, and deletes the old block automatically.
Given Input:
- Initial Capacity:
2 - Total Numbers to Add:
5
Expected Output:
Initial Capacity: 2
..Capacity doubled to 4..
..Capacity doubled to 8..
Final Data: 10 20 30 40 50
Final Capacity: 8
+ Hint
- Always use a temporary pointer to hold the result of
realloc. - If
reallocfails and returnsNULL, you don’t want to lose your original pointer to the existing data.
+ Show Solution
#include <stdio.h>
#include <stdlib.h>
int main() {
int capacity = 2, count = 0;
int *arr = malloc(capacity * sizeof(int));
printf("Initial Capacity: %d\n", capacity);
for (int i = 1; i <= 5; i++) {
if (count == capacity) {
capacity *= 2;
int *temp = realloc(arr, capacity * sizeof(int));
if (temp != NULL) arr = temp;
printf("..Capacity doubled to %d..\n", capacity);
}
arr[count++] = i * 10;
}
printf("Final Data: ");
for (int i = 0; i < count; i++) printf("%d ", arr[i]);
printf("\nFinal Capacity: %d\n", capacity);
free(arr);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
capacity *= 2: We grow the array exponentially. This is an industry-standard strategy to balance performance and memory usage.realloc(arr, capacity * sizeof(int)): It looks for a larger block. If it can’t find one at the current address, it moves the data to a new location and returns the new address.arr = temp: We update our pointer to the new address provided byrealloc.
Exercise 6: Function Pointers (Operation Selection)
Practice Problem: Create a “Calculator” function that performs an arithmetic operation on two integers using a function pointer. The program should demonstrate calling the add logic and then switching to the subtract logic via the same pointer.
Exercise Purpose: Function pointers allow you to treat logic as data. This is an essential intermediate skill used for implementing “callbacks” and designing modular code where the specific behavior of a function can be changed at runtime.
Given Input:
- Integers:
15, 5 - Operations:
add(a, b)andsubtract(a, b)
Expected Output:
Operation: ADD | Result: 20
Operation: SUB | Result: 10
+ Hint
- The syntax for a function pointer is
return_type (*pointer_name)(parameter_types). - You can assign a function name directly to this pointer.
+ Show Solution
#include <stdio.h>
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int main() {
int x = 15, y = 5;
// Declare a function pointer
int (*operation)(int, int);
// Point to add and execute
operation = add;
printf("Operation: ADD | Result: %d\n", operation(x, y));
// Point to subtract and execute
operation = subtract;
printf("Operation: SUB | Result: %d\n", operation(x, y));
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
int (*operation)(int, int): This tells the compiler thatoperationis a pointer to a function that returns anintand takes twointparameters.operation = add: In C, the name of a function is essentially its memory address. Here, we store the address of theaddfunction in our pointer.operation(x, y): The pointer is dereferenced to execute the code located at that memory address, behaving exactly like a direct function call.
Exercise 7: Custom strlen with Pointer Subtraction
Practice Problem: Write a function my_strlen(char *s) that calculates the length of a string without using any built-in library functions. Print the original string and the calculated length.
Exercise Purpose: This exercise demonstrates that strings are simply pointers to the first character of a null-terminated sequence. It also introduces the concept of pointer subtraction, which is an idiomatic and fast way to calculate distance in memory.
Given Input: String: "Hello World"
Expected Output:
String: Hello World
Calculated Length: 11
+ Hint
- Move a second pointer
pthrough the string until it hits the null terminator (\0). - The length is then the difference between the final pointer
pand the start pointers.
+ Show Solution
#include <stdio.h>
int my_strlen(char *s) {
char *p = s; // Copy of the starting address
while (*p != '\0') {
p++; // Move pointer forward
}
return p - s; // Subtract starting address from end address
}
int main() {
char text[] = "Hello World";
int length = my_strlen(text);
printf("String: %s\n", text);
printf("Calculated Length: %d\n", length);
return 0;
}Code language: C++ (cpp)
Explanation:
while (*p != '\0'): The loop continues until the character at the current addresspis the “null” character, which marks the end of all C strings.p++: Increments the address stored inpby the size of onechar(1 byte), moving us to the next character in memory.p - s: Subtracting two pointers of the same type results in the number of elements between them. This is more efficient than using a separate integer counter.
Exercise 8: String Reversal In-Place
Practice Problem: Write a function to reverse a string “in-place,” meaning you modify the original string without using a second array. Print the string before and after reversal.
Exercise Purpose: This exercise teaches memory efficiency operation with O(1) space complexity and how to manipulate char arrays using two-pointer logic (one at the start, one at the end).
Given Input: String: "PYnative"
Expected Output:
Before: PYnative
After: evitanYP
+ Hint
- Use two pointers: one at the start and one at the end.
- Swap the characters and move the pointers toward each other. (Swap the first character with the last, then the second with the second-to-last).
- Stop when the indices meet in the middle.
+ Show Solution
#include <stdio.h>
#include <string.h>
void reverse_string(char *str) {
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
char temp = str[i];
str[i] = str[len - 1 - i];
str[len - 1 - i] = temp;
}
}
int main() {
char my_str[] = "C-Prog";
printf("Before: %s\n", my_str);
reverse_string(my_str);
printf("After: %s\n", my_str);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
len / 2: We only loop halfway. If we went the full length, we would swap the characters back to their original positions.str[len - 1 - i]: This calculates the “mirror” index from the end. For index 0, it targets index 5 (if length is 6).char my_str[]: The string must be defined as an array. If defined aschar *s = "C-Prog", it is stored in read-only memory and would cause a crash if you tried to swap its characters.
Exercise 9: Anagram Checker (Frequency Array)
Practice Problem: Write a program to check if two strings are anagrams (contain the same letters in different orders). The program should display the two strings and the final result (Found/Not Found).
Exercise Purpose: This introduces the Frequency Array technique, a simple form of a hash map. Instead of expensive sorting, you use the character’s ASCII value as an index in an array to count occurrences.
Given Input:
- String 1:
"silent" - String 2:
"listen"
Expected Output:
String A: silent | String B: listen
Result: Anagrams Found
+ Hint
- Use an integer array of size 256 (for all ASCII characters).
- Increment counts for string 1 and decrement for string 2.
- If the array is all zeros at the end, they are anagrams.
+ Show Solution
#include <stdio.h>
#include <string.h>
int is_anagram(char *s1, char *s2) {
int count[256] = {0}; // Initialize all counts to 0
if (strlen(s1) != strlen(s2)) return 0;
for (int i = 0; s1[i] != '\0'; i++) {
count[(unsigned char)s1[i]]++; // Add for s1
count[(unsigned char)s2[i]]--; // Subtract for s2
}
for (int i = 0; i < 256; i++) {
if (count[i] != 0) return 0; // Any mismatch found
}
return 1;
}
int main() {
char a[] = "silent", b[] = "listen";
printf("String A: %s | String B: %s\n", a, b);
if (is_anagram(a, b)) printf("Result: Anagrams Found\n");
else printf("Result: Not Anagrams\n");
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
count[(unsigned char)s1[i]]++: We use the character itself (e.g., ‘a’ = 97) as the index in our count array. If ‘a’ appears, index 97 becomes 1.count[...]--: By subtracting for the second string, we “cancel out” the counts. If both strings have the same letters, every index in the array will eventually return to zero.- O(n) Time Complexity: This method is much faster than sorting both strings because it only looks at each character twice.
Exercise 10: Palindrome Checker (Two-Pointer Method)
Practice Problem: Use pointers to determine if a string is a palindrome. Print the word and a message indicating whether the word reads the same forward and backward.
Exercise Purpose: This demonstrates the efficiency of moving inward from both ends of a memory block simultaneously. It reinforces pointer arithmetic and conditional comparison.
Given Input: Word: "racecar"
Expected Output:
Testing word: racecar
Result: Is a Palindrome
+ Hint
- Set a
startpointer to the first character and anendpointer to the last. - While
startis less thanend, compare the characters they point to and move them toward the center.
+ Show Solution
#include <stdio.h>
#include <string.h>
int is_palindrome(char *str) {
char *start = str;
char *end = str + strlen(str) - 1;
while (end > start) {
if (*start != *end) return 0; // Mismatch
start++; // Move forward
end--; // Move backward
}
return 1;
}
int main() {
char word[] = "racecar";
printf("Testing word: %s\n", word);
if (is_palindrome(word)) printf("Result: Is a Palindrome\n");
else printf("Result: Not a Palindrome\n");
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
char *end = str + strlen(str) - 1: Calculates the address of the very last character before the null terminator.while (end > start): The loop stops once the pointers meet or cross in the middle.*start != *end: Dereferences both pointers to compare the characters. If “r” equals “r”, the pointers move; if they didn’t match, we would exit immediately.
Exercise 11: Word Counter
Practice Problem: Write a program that counts the number of words in a sentence, where words are separated by spaces. Print the sentence and the final word count.
Exercise Purpose: This teaches “State-based” logic. Instead of just counting spaces (which fails if there are multiple spaces between words), you track whether you are currently “inside” or “outside” of a word.
Given Input: Sentence: " Intermediate C is fun "
Expected Output:
Sentence: " Intermediate C is fun "
Word Count: 4
+ Hint
- Use a “state” variable (e.g.,
in_word = 0or1) to track whether you are currently inside a word or in the whitespace between words. - If you hit a non-space character and
in_wordis 0, you’ve found the start of a new word.
+ Show Solution
#include <stdio.h>
#include <ctype.h>
int count_words(char *s) {
int count = 0, in_word = 0;
while (*s) {
if (isspace(*s)) {
in_word = 0; // We are in whitespace
} else if (in_word == 0) {
in_word = 1; // Transition from space to letter
count++;
}
s++;
}
return count;
}
int main() {
char text[] = " Intermediate C is fun ";
printf("Sentence: \"%s\"\n", text);
printf("Word Count: %d\n", count_words(text));
return 0;
}Code language: C++ (cpp)
Explanation:
isspace(*s): A helper function from<ctype.h>that checks for spaces, tabs, or newlines.else if (in_word == 0): This condition only triggers when we hit the first letter of a word after coming from a space. This prevents multiple spaces from being counted as multiple words.count++: We only increment when we “enter” a word, making the count accurate even if the sentence starts or ends with extra spaces.
Exercise 12: Student Database (Struct Arrays)
Practice Problem: Create a struct Student containing a name, roll number, and GPA. Initialize an array of 3 students, then write logic to find and print the student with the highest GPA.
Exercise Purpose: Structs allow you to group variables of different types into a single logical unit. This exercise teaches how to manage “collections of records,” which is the precursor to handling database rows or object-oriented programming.
Given Input:
- Student 1:
{"Alice", 101, 3.8} - Student 2:
{"Bob", 102, 3.9} - Student 3:
{"Charlie", 103, 3.5}
Expected Output:
Initial Data:
Alice (GPA: 3.8)
Bob (GPA: 3.9)
Charlie (GPA: 3.5)
Top Student: Bob with GPA: 3.9
+ Hint
- Access struct members using the dot operator (
.). - Use a loop to iterate through the array. Keep track of the index of the student with the highest GPA found so far, then use that index to print the final result.
+ Show Solution
#include <stdio.h>
struct Student {
char name[50];
int roll;
float gpa;
};
int main() {
struct Student class[3] = {
{"Alice", 101, 3.8},
{"Bob", 102, 3.9},
{"Charlie", 103, 3.5}
};
int best_idx = 0;
printf("Initial Data:\n");
for(int i = 0; i < 3; i++) {
printf("%s (GPA: %.1f)\n", class[i].name, class[i].gpa);
if (class[i].gpa > class[best_idx].gpa) {
best_idx = i;
}
}
printf("\nTop Student: %s with GPA: %.1f\n", class[best_idx].name, class[best_idx].gpa);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
struct Student class[3]: This creates a contiguous block of memory large enough to hold three student “objects.”class[i].gpa: The dot (.) operator is used to access specific members inside a struct instance.best_idx = i: Instead of copying the whole struct, we just store the index of the “winner,” which is much more memory-efficient.
Exercise 13: Complex Number Arithmetic (Returning Structs)
Practice Problem: Define a struct for complex numbers ($a + bi$). Write a function that takes two complex number structs, adds them together, and returns a new struct containing the result.
Exercise Purpose: This demonstrates that functions can return entire structs by value. It teaches you how to design custom mathematical types and handle multi-variable data as a single return type.
Given Input:
- Complex 1:
3.0 + 4.0i - Complex 2:
1.0 + 2.0i
Expected Output:
Adding: (3.0 + 4.0i) and (1.0 + 2.0i)
Result: 4.0 + 6.0i
+ Hint
- Add the real parts and the imaginary parts separately inside the function.
- Use
typedefto make your code cleaner so you don’t have to typestructrepeatedly.
+ Show Solution
#include <stdio.h>
typedef struct {
float real;
float imag;
} Complex;
Complex add(Complex n1, Complex n2) {
Complex result;
result.real = n1.real + n2.real;
result.imag = n1.imag + n2.imag;
return result;
}
int main() {
Complex c1 = {3.0, 4.0}, c2 = {1.0, 2.0};
printf("Adding: (%.1f + %.1fi) and (%.1f + %.1fi)\n", c1.real, c1.imag, c2.real, c2.imag);
Complex sum = add(c1, c2);
printf("Result: %.1f + %.1fi\n", sum.real, sum.imag);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
typedef struct: This creates an alias, allowing us to useComplexas a standalone type name just likeintorfloat.Complex result: A local struct is created inside the function to hold the calculated values.return result: In C, when a struct is returned, the entire block of memory for that struct is copied back to the calling function.
Exercise 14: Time Difference (Normalization)
Practice Problem: Create a Time struct (hours, minutes, seconds). Write a function that calculates the absolute difference in total seconds between two time points.
Exercise Purpose: This exercise teaches the concept of Data Normalization. Instead of dealing with complex math (like “borrowing” minutes), you convert all data to a single base unit (seconds) to perform simple arithmetic.
Given Input:
- Start:
10h 30m 00s - End:
12h 15m 30s
Expected Output:
Time 1: 10:30:00 (37800 sec)
Time 2: 12:15:30 (44130 sec)
Difference: 6330 seconds
+ Hint
- Convert both times into total seconds since the start of the day (
total = (h * 3600) + (m * 60) + s), then subtract them. - Use the
abs()function fromstdlib.hto ensure the result is positive.
+ Show Solution
#include <stdio.h>
#include <stdlib.h>
struct Time { int h, m, s; };
int to_seconds(struct Time t) {
return (t.h * 3600) + (t.m * 60) + t.s;
}
int main() {
struct Time start = {10, 30, 0};
struct Time end = {12, 15, 30};
int s1 = to_seconds(start);
int s2 = to_seconds(end);
printf("Time 1: %02d:%02d:%02d (%d sec)\n", start.h, start.m, start.s, s1);
printf("Time 2: %02d:%02d:%02d (%d sec)\n", end.h, end.m, end.s, s2);
int diff = abs(s2 - s1);
printf("Difference: %d seconds\n", diff);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
to_seconds(struct Time t): This helper function “flattens” the struct into a single integer, making the comparison trivial.%02d: This format specifier ensures that the time prints with leading zeros (e.g., “05” instead of “5”), making it look like a digital clock.abs(s2 - s1): This ensures that regardless of which time is “start” or “end,” you get a positive duration.
Exercise 15: Nested Structs (Composition)
Practice Problem: Create a Point struct (x, y) and a Circle struct that contains a Point as its center and a radius. Calculate the area of the circle using the nested center coordinates.
Exercise Purpose: This introduces Composition, where you build a complex struct using other structs as building blocks. It is essential for organizing data in graphics, physics engines, and mapping software.
Given Input:
- Center:
x=0, y=0 - Radius:
5.0
Expected Output:
Circle Center: (0.0, 0.0)
Circle Radius: 5.0
Calculated Area: 78.54
+ Hint
To access the x-coordinate from a circle variable c, use double-dot notation: c.center.x.
+ Show Solution
#include <stdio.h>
typedef struct { float x, y; } Point;
typedef struct { Point center; float radius; } Circle;
int main() {
Circle myCircle = {{0.0, 0.0}, 5.0};
float area = 3.14159 * myCircle.radius * myCircle.radius;
printf("Circle Center: (%.1f, %.1f)\n", myCircle.center.x, myCircle.center.y);
printf("Circle Radius: %.1f\n", myCircle.radius);
printf("Calculated Area: %.2f\n", area);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
Point center: Inside theCircledefinition, we don’t just store floats; we store an actualPointtype.{{0.0, 0.0}, 5.0}: The nested curly braces initialize the innerPointstruct first, then theradius.myCircle.center.x: The compiler first looks intomyCircleto find thecenterstruct, then looks intocenterto find thexfloat.
Exercise 16: Unions vs. Structs (Memory Sharing)
Practice Problem: Define a union Data that can hold an int or a float. Assign a value to the integer, print it, then assign a value to the float and observe how it affects the memory of the integer.
Exercise Purpose: Unions are a special data type where all members share the same memory location. This exercise teaches you about memory conservation and how C interprets the same raw bits as different data types.
Given Input:
- Integer value:
10 - Float value:
220.5
Expected Output:
Step 1: Assigned Int = 10
Memory state (as float): 0.000000
Step 2: Assigned Float = 220.5
Memory state (as int): 1130135552 (Now Overwritten!)
+ Hint
- A union’s size is equal to its largest member.
- Only one member can be used at a time; updating one will overwrite the other.
+ Show Solution
#include <stdio.h>
union Data {
int i;
float f;
};
int main() {
union Data d;
d.i = 10;
printf("Step 1: Assigned Int = %d\n", d.i);
printf("Memory state (as float): %f\n", d.f);
d.f = 220.5;
printf("\nStep 2: Assigned Float = %.1f\n", d.f);
printf("Memory state (as int): %d (Now Overwritten!)\n", d.i);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
union Data d: This allocates only 4 bytes of memory (enough for either oneintor onefloat).- Shared Memory: In Step 1, when we print
d.fafter assigningd.i, we see a strange decimal number. This is because the computer is trying to read the integer10bits as if they were a floating-point number. - Overwriting: In Step 2, assigning
d.fphysically overwrites the bytes that stored10. This shows why you must track which member of a union is currently “active.”
Exercise 17: File Copy (Character Stream)
Practice Problem: Write a program that opens an existing text file (source.txt) and copies its entire content into a new file (destination.txt) character by character. Print a message to the console once the copy is complete.
Exercise Purpose: This exercise introduces the “Stream” concept. Instead of loading a massive file into RAM (which could crash your program), you process it one byte at a time. It also teaches the importance of checking for NULL file pointers.
Given Input:
- Source File:
source.txt(contains “Hello File I/O!”) - Destination File:
destination.txt
Expected Output:
Starting copy process...
File copied successfully.
+ Hint
- Use
fgetc()to read a character andfputc()to write it. - The loop should continue until
fgetc()returns the special constantEOF(End Of File).
+ Show Solution
#include <stdio.h>
int main() {
FILE *src = fopen("source.txt", "r");
FILE *dest = fopen("destination.txt", "w");
if (src == NULL || dest == NULL) {
printf("Error: Could not open files.\n");
return 1;
}
char ch;
printf("Starting copy process...\n");
while ((ch = fgetc(src)) != EOF) {
fputc(ch, dest);
}
printf("File copied successfully.\n");
fclose(src);
fclose(dest);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
fopen("source.txt", "r"): Opens the file in “read” mode. If the file doesn’t exist, it returnsNULL.while ((ch = fgetc(src)) != EOF): This is a classic C pattern. It reads a character, assigns it toch, and checks if it’s the end of the file all in one line.fclose(src): Closing files is mandatory. It releases the file handle back to the Operating System and ensures all data is physically written to the disk.
Exercise 18: Line Counter
Practice Problem: Write a program that opens a text file and counts how many lines it contains by detecting the newline character (\n). Print the total count to the console.
Exercise Purpose: This exercise teaches how to parse file data for specific patterns. It reinforces that text files are just sequences of characters, and “lines” are simply characters separated by \n.
Given Input:
- A file
data.txtwith 3 lines of text.
Expected Output:
Total lines: 3
+ Hint
- Every time
fgetc()encounters\n, increment a counter. - Note that the last line might not have a
\n, so you may need to account for that.
+ Show Solution
#include <stdio.h>
int main() {
FILE *fptr = fopen("data.txt", "r");
if (fptr == NULL) return 1;
int count = 0;
char ch;
while ((ch = fgetc(fptr)) != EOF) {
if (ch == '\n') {
count++;
}
}
printf("Total Newline Characters: %d\n", count);
printf("Estimated Total Lines: %d\n", count + 1);
fclose(fptr);
return 0;
}Code language: C++ (cpp)
Explanation of Solutions:
if (ch == '\n'): This identifies the specific character used by the system to move to a new line.count + 1: We add one to the final count because if a file has one line of text but no newline at the end, the loop would count 0, even though a line of text exists.
Exercise 19: Binary Struct Storage
Practice Problem: Write a program to save an array of struct Student to a binary file and then read it back. You must demonstrate that the data persists by printing the original array, clearing the memory, and then printing the data retrieved from the file.
Exercise Purpose: Binary storage is different from text storage because it writes the exact bit-pattern of the RAM to the disk. This is much faster and more space-efficient than text files. This exercise teaches you how to handle “Deep Persistence,” which is essential for database engines and game save files.
Given Input:
struct Student { char name[20]; int age; };- Initial Data:
{"Jessa", 20}, {"Kelly", 22} - File Name:
students.bin
Expected Output:
--- Existing Data in Memory ---
Jessa, 20
Kelly, 22
Data written successfully in binary file
--- Data Read from Binary File ---
Jessa, 20
Kelly, 22
+ Hint
- Use
fwriteto send the raw memory of the struct array to the disk. - To read it back, use
freadwith the same struct size and count to ensure the bytes are mapped correctly back into the array.
+ Show Solution
#include <stdio.h>
struct Student { char name[20]; int age; };
int main() {
struct Student out[2] = {{"User1", 20}, {"User2", 22}}, in[2];
printf("--- Existing Data in Memory ---\n");
for(int i=0; i<2; i++) printf("%s, %d\n", out[i].name, out[i].age);
FILE *f = fopen("students.bin", "wb");
if (!f) return 1;
fwrite(out, sizeof(struct Student), 2, f);
fclose(f);
// Read back into 'in' array
f = fopen("students.bin", "rb");
if (!f) return 1;
fread(in, sizeof(struct Student), 2, f);
fclose(f);
printf("\n--- Data Read from Binary File ---\n");
for(int i=0; i<2; i++) printf("%s, %d\n", in[i].name, in[i].age);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
fwrite(out, sizeof(struct Student), 2, f): This line tells C to take the memory address ofout, measure how big oneStudentis, and write 2 of them directly to the file stream.- Binary Mode (
"wb","rb"): The ‘b’ flag is crucial; it tells the OS not to translate newline characters, keeping the raw bit-pattern of the integers and strings intact. fread(in, ...): This performs the exact reverse offwrite. It fills the emptyinarray with the bytes found in the file. Since the struct definition is the same, the data fits back into thenameandagefields perfectly.
Exercise 20: Singly Linked List (Insertion at Head)
Practice Problem: Implement a function to insert a new integer node at the beginning of a linked list. The program should display the list before and after the insertion to show how the “Head” pointer moves.
Exercise Purpose: Linked lists are the foundation of dynamic data structures. Unlike arrays, they don’t need contiguous memory. This exercise teaches “Pointer to a Pointer” logic, which is necessary because the function needs to modify the address stored in the head variable back in main.
Given Input:
- Initial Node:
10 - New value to insert:
20
Expected Output:
Head data: 20
+ Hint
- To modify the
headpointer from within a function, you must pass its address (&head). - Inside the function, dereference it once (
*head_ref) to access the actual pointer.
+ Show Solution
#include <stdio.h>
#include <stdlib.h>
struct Node { int data; struct Node *next; };
void push(struct Node **head_ref, int new_val) {
struct Node *new_node = malloc(sizeof(struct Node));
new_node->data = new_val;
new_node->next = *head_ref; // New node points to old head
*head_ref = new_node; // Head now points to new node
}
void printList(struct Node *n) {
while (n != NULL) { printf("%d -> ", n->data); n = n->next; }
printf("NULL\n");
}
int main() {
struct Node *head = malloc(sizeof(struct Node));
head->data = 10; head->next = NULL;
printf("Existing List: "); printList(head);
push(&head, 20);
printf("After Push(20): "); printList(head);
return 0;
}Code language: C++ (cpp)
Explanation:
malloc(sizeof(struct Node)): Allocates a block of memory on the heap large enough for one integer and one pointer.new_node->next = *head_ref: This “wires” our new node to the existing list. The new node’s “next” arm now holds the address of the node that used to be first.*head_ref = new_node: We update theheadvariable inmainto the address of our new node. The new node is now officially the first element in the chain.
Exercise 21: Linked List Search
Practice Problem: Create a search function that traverses a linked list to find a specific integer. The program should print the full list first, then output whether the target value exists.
Exercise Purpose: Searching a linked list is a linear operation (O(n)). Because you can’t jump to a specific index like in an array, you must follow the “chain” of pointers. This teaches you how to traverse memory dynamically and reinforces the concept of the Null Terminator in data structures.
Given Input:
- Linked List:
5 -> 15 -> 25 -> NULL - Search Key:
15
Expected Output:
Current List: 5 -> 15 -> 25 -> NULL
Search Result for 15: Found
+ Hint
- Use a
whileloop to traverse the list:current = current->next. - Stop when
current == NULL.
+ Show Solution
#include <stdio.h>
#include <stdlib.h>
struct Node { int data; struct Node *next; };
int search(struct Node *head, int key) {
struct Node *curr = head;
while (curr != NULL) {
if (curr->data == key) return 1;
curr = curr->next;
}
return 0;
}
int main() {
struct Node n3 = {25, NULL}, n2 = {15, &n3}, n1 = {5, &n2};
printf("Current List: 5 -> 15 -> 25 -> NULL\n");
int found = search(&n1, 15);
printf("Search Result for 15: %s\n", found ? "Found" : "Not Found");
return 0;
}Code language: C++ (cpp)
Explanation:
struct Node *curr = head: We create a temporary pointercurrso we don’t “lose” the start of the list.curr = curr->next: This is the engine of the search. It updatescurrto hold the memory address stored in thenextfield of the current node, effectively jumping to the next block of data.while (curr != NULL): This ensures we don’t try to access memory at address0(NULL), which would cause a segmentation fault.
Exercise 22: Stack (Array-based)
Practice Problem: Implement a Stack using a fixed array. Demonstrate the “Push” operation by showing the stack contents and the top index before and after adding a new value.
Exercise Purpose: A stack is a restricted data structure. It limits how you access data to ensure a specific order (LIFO). This is the logic used for the “Undo” feature in text editors or the “Back” button in web browsers. It teaches you how to manage data boundaries and the concept of Overflow and Underflow.
Given Input:
- Array:
int stack[5] - Current State:
[50],top = 0 - Value to Push:
100
Expected Output:
Before Push: top index = 0, value = 50
After Push: top index = 1, value = 100
+ Hint
topstarts at -1.pushincrementstopbefore adding,popreturns the value and decrementstop.
+ Show Solution
#include <stdio.h>
struct Stack { int items[5]; int top; };
void push(struct Stack *s, int val) {
s->items[++(s->top)] = val;
}
int main() {
struct Stack s = {{50}, 0};
printf("Before Push: top index = %d, value = %d\n", s.top, s.items[s.top]);
push(&s, 100);
printf("After Push: top index = %d, value = %d\n", s.top, s.items[s.top]);
return 0;
}Code language: C++ (cpp)
Explanation:
++(s->top): This is a pre-increment. It changes thetopvalue from0to1before it is used as an index.s->items[...] = val: The value100is placed intoitems[1].- State Management: By keeping
topinside the struct with the array, we ensure the index and the data are always passed together to any function, maintaining a clean organizational structure.
Exercise 23: Queue (Enqueue Operation)
Practice Problem: Implement a Queue using a linked list. Show the state of the front and rear pointers before and after an enqueue operation.
Exercise Purpose: Queues are used for scheduling tasks (like a printer queue). By using a linked list instead of an array, the queue can grow as large as the system’s memory allows. Having both a front and rear pointer allows both addition and removal to happen in O(1) time.
Given:
- Initial Queue:
[10](Front and Rear both point to 10) - Value to Enqueue:
20
Expected Output:
Before: Front = 10, Rear = 10
After: Front = 10, Rear = 20
+ Hint
- In a queue, you add to the
rear. - You must update the
nextpointer of the currentrearnode to point to the new node, and then update therearpointer itself.
+ Show Solution
#include <stdio.h>
#include <stdlib.h>
struct Node { int data; struct Node *next; };
struct Queue { struct Node *front, *rear; };
void enqueue(struct Queue *q, int val) {
struct Node *temp = malloc(sizeof(struct Node));
temp->data = val; temp->next = NULL;
q->rear->next = temp;
q->rear = temp;
}
int main() {
struct Node *n1 = malloc(sizeof(struct Node));
n1->data = 10; n1->next = NULL;
struct Queue q = {n1, n1};
printf("Before: Front = %d, Rear = %d\n", q.front->data, q.rear->data);
enqueue(&q, 20);
printf("After: Front = %d, Rear = %d\n", q.front->data, q.rear->data);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
q->rear->next = temp: Sincerearis pointing to the last node (10), we access that node’snextpointer and give it the address of our new node (20).q->rear = temp: We move therearlabel to the new node. Now,frontstill points to 10, butrearpoints to 20.- Result: This allows us to maintain a First-In-First-Out order, as we can always find the start via
frontand the end viarearinstantly.
Exercise 24: Delete Node by Value
Practice Problem: Write a function to delete a specific node from a linked list. Print the list’s data before the operation and the remaining data after to prove the node was successfully unlinked and the memory was freed.
Exercise Purpose: Deletion is the trickiest part of linked list management. If you don’t “bridge” the previous node to the next node before freeing, you break the chain and lose the rest of your list. This exercise is vital for understanding Manual Memory Management and pointer redirection.
Given Input:
- Initial List:
10 -> 20 -> 30 -> NULL - Target to Delete:
20
Expected Output:
Before Deletion: 10 -> 20 -> 30
After Deletion: 10 -> 30
+ Hint
- You need to keep track of two nodes: the one you are checking (
temp) and the one immediately before it (prev). - When you find the match, connect
prev->nexttotemp->nextto bypass the target.
+ Show Solution
#include <stdio.h>
#include <stdlib.h>
struct Node { int data; struct Node *next; };
void deleteNode(struct Node **head, int key) {
struct Node *temp = *head, *prev;
while (temp != NULL && temp->data != key) {
prev = temp; temp = temp->next;
}
prev->next = temp->next;
free(temp);
}
int main() {
struct Node *n3 = malloc(sizeof(struct Node)), *n2 = malloc(sizeof(struct Node)), *n1 = malloc(sizeof(struct Node));
n1->data = 10; n1->next = n2; n2->data = 20; n2->next = n3; n3->data = 30; n3->next = NULL;
printf("Before Deletion: 10 -> 20 -> 30\n");
deleteNode(&n1, 20);
printf("After Deletion: 10 -> %d\n", n1->next->data);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
while (temp != NULL && temp->data != key): This loop slides two pointers along the list.prevstays one step behindtemp.prev->next = temp->next: This is the “bridging” step. By taking the address of the node after 20 and giving it to the node before 20, the list now flows from 10 directly to 30.free(temp): This is critical. It tells the operating system that the memory used by node 20 is now available for other uses, preventing a memory leak.
Exercise 25: Binary Search
Practice Problem: Implement a binary search on a sorted array. Print the low and high indices at every step to show how the algorithm cuts the search area in half until the target is found.
Exercise Purpose: Binary search is significantly faster (O(log n)) than linear search (O(n)). For an array of 1 million items, linear search might take 1,000,000 steps, while binary search takes only about 20. This exercise emphasizes why Sorted Data is so valuable in computer science.
Given Input:
- Sorted Array:
{10, 20, 30, 40, 50} - Target:
40
Expected Output:
Array: 10, 20, 30, 40, 50 | Target: 40
Searching between indices 0 and 4
Searching between indices 3 and 4
Found at index: 3
+ Hint
- The middle point should be recalculated inside the
whileloop. - If the target is greater than the middle value, move the
lowindex tomid + 1.
+ Show Solution
#include <stdio.h>
int binarySearch(int arr[], int n, int x) {
int low = 0, high = n - 1;
while (low <= high) {
int mid = (low + high) / 2;
printf("Searching between indices %d and %d\n", low, high);
if (arr[mid] == x) return mid;
if (arr[mid] < x) low = mid + 1;
else high = mid - 1;
}
return -1;
}
int main() {
int arr[] = {10, 20, 30, 40, 50};
printf("Array: 10, 20, 30, 40, 50 | Target: 40\n");
int res = binarySearch(arr, 5, 40);
printf("Found at index: %d\n", res);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
mid = (low + high) / 2: This finds the center of the current search bounds.low = mid + 1: If our target (40) is higher than our middle (30), we know the target cannot be in the lower half. We move our starting point to just past the middle.- Logarithmic Time: Each print statement shows the range shrinking. This
O(log n)efficiency is why binary search is used for massive databases.
Exercise 26: Bubble Sort vs Selection Sort
Practice Problem: Perform a Selection Sort on an unsorted array. Print the array after the first full swap to demonstrate how the smallest element is “selected” and moved to the front.
Exercise Purpose: While both have O(n^2) time complexity, Selection Sort is generally better than Bubble Sort because it performs fewer writes to memory. This teaches you that “Efficiency” isn’t just about CPU cycles, but also about minimizing expensive memory operations.
Given Input: Array: {64, 25, 12, 22, 11}
Expected Output:
Original: 64, 25, 12, 22, 11
After 1st swap: 11, 25, 12, 22, 64
+ Hint
Use a secondary loop to find the index of the smallest number in the array. Swap that smallest number with the element at arr[0].
+ Show Solution
#include <stdio.h>
void selectionSort(int arr[], int n) {
int min_idx = 0;
for (int j = 1; j < n; j++)
if (arr[j] < arr[min_idx]) min_idx = j;
int temp = arr[min_idx];
arr[min_idx] = arr[0];
arr[0] = temp;
}
int main() {
int arr[] = {64, 25, 12, 22, 11};
printf("Original: 64, 25, 12, 22, 11\n");
selectionSort(arr, 5);
printf("After 1st swap: %d, %d, %d, %d, %d\n", arr[0], arr[1], arr[2], arr[3], arr[4]);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
- Outer Search: The code scans every element to find that
11is the absolute minimum. tempSwap: Standard three-step swap logic using a temporary variable to move11to the front and64to where11used to be.- Result: After the first pass, the first element of the array is guaranteed to be in its final sorted position.
Exercise 27: Bitwise Toggle
Practice Problem: Use bitwise operators to flip the status of a specific bit. Print the value of the number before and after the toggle to show how binary changes affect decimal values.
Exercise Purpose: Bitwise operations are the fastest operations a CPU can perform. Toggling bits is common in embedded systems (like turning a single LED on/off in a register) or in cryptography. This exercise helps you think about how data is actually represented at the hardware level.
Given Input:
- Number:
5(Binary0101) - Bit Position to toggle:
1(The second bit from the right)
Expected Output:
Initial Value: 5 (Binary 0101)
After Toggling Bit 1: 7 (Binary 0111)
+ Hint
- Use the bitwise XOR (
^) operator. XORing a bit with1will flip it, while XORing it with0will leave it alone. - Use
1 << posto create the mask.
+ Show Solution
#include <stdio.h>
int main() {
int num = 5;
int pos = 1;
printf("Initial Value: %d (Binary 0101)\n", num);
num ^= (1 << pos);
printf("After Toggling Bit 1: %d (Binary 0111)\n", num);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
1 << pos: This takes the binary number0001and shifts the1to the left by 1 spot, resulting in0010. This is our “mask.”num ^= mask: The XOR operator compares0101and0010. Since the second bit is different in each, it becomes a1.- Decimal Change: In decimal, we changed the “2’s place” bit from 0 to 1, effectively adding 2 to the number (5 + 2 = 7).
Exercise 28: Decimal to Binary (Bitmasking)
Practice Problem: Create a function that displays the binary representation of a decimal number. Print the decimal value first, followed by its 8-bit binary string.
Exercise Purpose: This exercise bridges the gap between high-level numbers and low-level bits. It teaches you how to “Mask” data to extract specific information.
Given Input: Number: 10
Expected Output:
Decimal: 10
Binary (8-bit): 00001010
+ Hint
Use a loop that runs from 7 down to 0. In each iteration, shift the number right by i positions and use & 1 to “mask” and extract only the rightmost bit.
+ Show Solution
#include <stdio.h>
void printBinary(int n) {
for (int i = 7; i >= 0; i--) {
int bit = (n >> i) & 1;
printf("%d", bit);
}
printf("\n");
}
int main() {
int num = 10;
printf("Decimal: %d\n", num);
printf("Binary (8-bit): ");
printBinary(num);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
n >> i: This moves the bit we want to inspect all the way to the “ones” column.& 1: The AND operator with1acts like a filter. It ignores all other bits and only tells us if the current rightmost bit is a1or0.- Reversed Loop: We start the loop at
7and go down to0because we read binary strings from left (most significant) to right (least significant).
Exercise 29: Sorting Structure Data
Practice Problem: Define an Employee struct containing a name and a salary. Create an array of 3 employees and write a program to sort them in ascending order based on their salary. Print the list before and after sorting.
Exercise Purpose: In real-world applications, data is rarely just a list of numbers; it is usually a collection of related attributes (structs). This exercise teaches you how to apply sorting logic to specific fields within a complex data type while keeping the entire record intact.
Given Input:
- Employee 1:
{"John", 50000} - Employee 2:
{"Alice", 75000} - Employee 3:
{"Bob", 45000}
Expected Output:
Before Sorting (Salary):
John: 50000
Alice: 75000
Bob: 45000
After Sorting (Salary):
Bob: 45000
John: 50000
Alice: 75000
+ Hint
- Use the Bubble Sort algorithm.
- When comparing, only check the
salaryfield, but when swapping, swap the entireEmployeestruct to ensure the name stays with the correct salary.
+ Show Solution
#include <stdio.h>
#include <string.h>
struct Employee {
char name[20];
float salary;
};
void sortEmployees(struct Employee emp[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (emp[j].salary > emp[j + 1].salary) {
struct Employee temp = emp[j];
emp[j] = emp[j + 1];
emp[j + 1] = temp;
}
}
}
}
int main() {
struct Employee staff[3] = {{"John", 50000}, {"Alice", 75000}, {"Bob", 45000}};
printf("Before Sorting (Salary):\n");
for(int i=0; i<3; i++) printf("%s: %.0f\n", staff[i].name, staff[i].salary);
sortEmployees(staff, 3);
printf("\nAfter Sorting (Salary):\n");
for(int i=0; i<3; i++) printf("%s: %.0f\n", staff[i].name, staff[i].salary);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
if (emp[j].salary > emp[j + 1].salary): This targets only the numerical value for comparison.struct Employee temp = emp[j]: By using the struct type for thetempvariable, C automatically copies all internal fields (both name and salary) during the swap.- Bubble Sort Logic: The nested loops ensure that the “heaviest” salary floats to the end of the array in each pass.
Exercise 30: Second Largest Element in an Array
Practice Problem: Write a program to find the second largest integer in an array of size 5. The program must find this in a single pass (O(n)) without sorting the array.
Exercise Purpose: Sorting an array to find the second largest is O(n log n). This exercise teaches you how to optimize performance by maintaining two state variables (max and secondMax) simultaneously during a single traversal.
Given Input: Array: {12, 35, 1, 10, 34}
Expected Output:
Array: 12, 35, 1, 10, 34
Largest: 35 | Second Largest: 34
+ Hint
- Initialize
maxandsecondMaxto a very small number. - If the current element is larger than
max, updatesecondMaxto be the oldmax, and then updatemaxto the current element.
+ Show Solution
#include <stdio.h>
#include <limits.h>
int main() {
int arr[5] = {12, 35, 1, 10, 34};
int max = INT_MIN, secondMax = INT_MIN;
printf("Array: 12, 35, 1, 10, 34\n");
for (int i = 0; i < 5; i++) {
if (arr[i] > max) {
secondMax = max;
max = arr[i];
} else if (arr[i] > secondMax && arr[i] != max) {
secondMax = arr[i];
}
}
printf("Largest: %d | Second Largest: %d\n", max, secondMax);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
secondMax = max: Before we replace the “king” (max), we demote the current king to the “vice-king” (secondMax).arr[i] != max: This check ensures that if the largest number appears twice in the array, thesecondMaxstill looks for a value strictly smaller than the absolute max.INT_MIN: This macro from<limits.h>represents the smallest possible integer, ensuring our comparisons work even if the array contains negative numbers.
Exercise 31: Merge Two Sorted Arrays
Practice Problem: Given two arrays that are already sorted, merge them into a third array such that the third array is also sorted. Print the two source arrays and the final merged result.
Exercise Purpose: This is the core logic behind the “Merge Sort” algorithm. It teaches you how to manage three different pointers simultaneously and how to handle “leftover” elements when one array is shorter than the other.
Given Input:
- Array 1:
{1, 3, 5} - Array 2:
{2, 4, 6}
Expected Output:
Array 1: 1, 3, 5 | Array 2: 2, 4, 6
Merged: 1 2 3 4 5 6
+ Hint
Compare the current elements of both arrays. Pick the smaller one, put it in the third array, and move the pointer for that array forward.
+ Show Solution
#include <stdio.h>
int main() {
int a[] = {1, 3, 5}, b[] = {2, 4, 6};
int res[6], i = 0, j = 0, k = 0;
printf("Array 1: 1, 3, 5 | Array 2: 2, 4, 6\n");
while (i < 3 && j < 3) {
if (a[i] < b[j]) res[k++] = a[i++];
else res[k++] = b[j++];
}
while (i < 3) res[k++] = a[i++]; // Copy leftovers
while (j < 3) res[k++] = b[j++];
printf("Merged: ");
for (int x = 0; x < 6; x++) printf("%d ", res[x]);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
while (i < 3 && j < 3): This loop runs until one of the two source arrays is completely exhausted.res[k++] = a[i++]: This is a compact way to assign the value and then increment both the result index and the source index.- Leftover Loops: The final two
whileloops ensure that if one array (like{1, 2}) finishes but the other (like{10, 11, 12}) still has elements, those remaining elements are appended to the end.
Exercise 32: Remove Duplicate Elements
Practice Problem: Write a program to remove duplicate integers from a sorted array. The program should shift elements to the left to “delete” duplicates and return the new length of the array.
Exercise Purpose: This exercise teaches in-place array manipulation. Instead of creating a second “clean” array, you learn how to use a “slow-moving” pointer to overwrite the duplicates with unique values.
Given Input: Sorted Array: {1, 2, 2, 3, 4, 4, 5}
Expected Output:
Original: 1, 2, 2, 3, 4, 4, 5
Unique: 1 2 3 4 5
+ Hint
- Keep a pointer
jfor unique elements. - Iterate through the array with
i, and every timearr[i]is different fromarr[j], incrementjand copyarr[i]toarr[j].
+ Show Solution
#include <stdio.h>
int main() {
int arr[] = {1, 2, 2, 3, 4, 4, 5};
int n = 7, j = 0;
printf("Original: 1, 2, 2, 3, 4, 4, 5\n");
for (int i = 0; i < n - 1; i++) {
if (arr[i] != arr[i + 1]) {
arr[j++] = arr[i];
}
}
arr[j++] = arr[n - 1]; // Handle the last element
printf("Unique: ");
for (int i = 0; i < j; i++) printf("%d ", arr[i]);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
- In-place logic: We are using the same
arrto store the unique values, effectively overwriting the duplicates as we find them. arr[i] != arr[i + 1]: Since the array is sorted, duplicates are guaranteed to be neighbors. If the next element is different, the current one is the last occurrence of that specific value.- Final Assignment: The loop stops before the last element, so we manually add
arr[n-1]to the unique list.
Exercise 33: Most Frequent Character
Practice Problem: Write a program to find which character appears most often in a string. Print the string and the winning character with its count.
Exercise Purpose: This reinforces the “Frequency Array” or “Hashing” concept. It maps characters (keys) to their counts (values), which is an essential pattern for solving string-based optimization problems.
Given Input: String: "success"
Expected Output:
String: success
Most Frequent: 's' (appears 3 times)
+ Hint
- Create an integer array of size 256.
- Use each character’s ASCII value as an index to increment the count. Then, find the index with the highest value.
+ Show Solution
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "success";
int freq[256] = {0}, maxCount = 0;
char result;
for (int i = 0; str[i] != '\0'; i++) {
freq[(unsigned char)str[i]]++;
}
for (int i = 0; i < 256; i++) {
if (freq[i] > maxCount) {
maxCount = freq[i];
result = (char)i;
}
}
printf("String: %s\n", str);
printf("Most Frequent: '%c' (appears %d times)\n", result, maxCount);
return 0;
}Code language: C++ (cpp)
Explanation:
freq[(unsigned char)str[i]]++: We cast tounsigned charto ensure characters outside the standard 127 ASCII range (like accented letters) don’t produce negative indices.- Two-Step Process: First, we build the “map” of counts. Second, we scan that map to find the “peak.” This is a highly efficient $O(n)$ solution.
Exercise 34: Fibonacci Series (Recursion)
Practice Problem: Generate the first 10 terms of the Fibonacci series using a recursive function. Print the series in a single line.
The Fibonacci sequence formula is a recursive rule: F(n) = F(n-1) + F(n-2), meaning each number is the sum of the two preceding ones, starting with base cases F(0) = 0 and F(1) = 1 (0, 1, 1, 2, 3, 5, 8…).
Exercise Purpose: This is the classic introduction to Recursion. It teaches the two requirements for a recursive function: the Base Case (to stop the loop) and the Recursive Step (the function calling itself).
Given Input: Terms to generate: 10
Expected Output:
Fibonacci Series (10 terms): 0 1 1 2 3 5 8 13 21 34
+ Hint
+ Show Solution
#include <stdio.h>
int fibonacci(int n) {
if (n <= 1) return n; // Base case
return fibonacci(n - 1) + fibonacci(n - 2); // Recursive call
}
int main() {
int terms = 10;
printf("Fibonacci Series (10 terms): ");
for (int i = 0; i < terms; i++) {
printf("%d ", fibonacci(i));
}
printf("\n");
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
- Base Case (
n <= 1): Without this, the function would call itself infinitely until the program crashed. - Recursive Step: The function calculates a value by asking itself for the two previous values. This creates a “tree” of calls that eventually reaches the base cases.
- Cost of Recursion: While elegant, this specific recursive method is actually slow for large numbers (
O(2^n)) because it recalculates the same values many times. It serves as a great lesson on when to use recursion vs. iteration.
Exercise 35: Intersection of Two Arrays
Practice Problem: Write a program that finds the common elements between two integer arrays. The program should store these common elements in a third array and print the result.
Exercise Purpose: This problem introduces basic set theory in programming. It teaches you how to perform “membership testing” by comparing elements of one dataset against another, a fundamental task in database joins and data filtering.
Given Input:
- Array 1:
{1, 2, 3, 4, 5} - Array 2:
{3, 4, 5, 6, 7}
Expected Output:
Array 1: {1, 2, 3, 4, 5}
Array 2: {3, 4, 5, 6, 7}
Intersection: 3 4 5
+ Hint
- Use a nested loop to compare each element of the first array with every element of the second.
- If a match is found, ensure you haven’t already added it to your “intersection” list to handle potential duplicates
+ Show Solution
#include <stdio.h>
int main() {
int a1[] = {1, 2, 3, 4, 5}, a2[] = {3, 4, 5, 6, 7};
int intersect[5], k = 0;
printf("Array 1: {1, 2, 3, 4, 5}\nArray 2: {3, 4, 5, 6, 7}\n");
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (a1[i] == a2[j]) {
intersect[k++] = a1[i];
break; // Move to next element in a1
}
}
}
printf("Intersection: ");
for (int i = 0; i < k; i++) printf("%d ", intersect[i]);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
- Nested Loops: The outer loop picks a number from
a1, and the inner loop scansa2to see if that number exists there. breakStatement: Once a match is found, we don’t need to keep checking the rest ofa2for that specific number, saving processing time.- Result Storage: The
kvariable acts as a cursor for theintersectarray, only incrementing when a common element is actually found.
Exercise 36: Move Zeros to the End
Practice Problem: Write a program that takes an array containing some zeros and moves all those zeros to the end of the array without changing the relative order of the non-zero elements.
Exercise Purpose: This is a classic “array partitioning” problem. It teaches you how to maintain two pointers. one for the current scan and one for the “write position” allowing you to modify the array in a single pass (O(n)).
Given Input: Array: {0, 1, 0, 3, 12}
Expected Output:
Original: {0, 1, 0, 3, 12}
Modified: 1 3 12 0 0
+ Hint
- Iterate through the array. If the current element is not zero, put it at the “non-zero” pointer position and increment that pointer.
- After the loop, fill the remaining positions with zeros.
+ Show Solution
#include <stdio.h>
int main() {
int arr[] = {0, 1, 0, 3, 12};
int n = 5, count = 0; // count tracks position for non-zero elements
printf("Original: {0, 1, 0, 3, 12}\n");
for (int i = 0; i < n; i++) {
if (arr[i] != 0) {
arr[count++] = arr[i];
}
}
// Fill the rest with zeros
while (count < n) {
arr[count++] = 0;
}
printf("Modified: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
- First Pass: The loop effectively “squeezes” all non-zero numbers to the front of the array in their original order.
count++: Thecountvariable always points to where the next non-zero number should go.- Final Padding: The
whileloop starts from wherevercountleft off and fills the rest of the array slots with zero.
Exercise 37: Sort Strings Alphabetically (Pointers)
Practice Problem: Create an array of strings (names) and sort them in alphabetical order using pointers and the strcmp function.
Exercise Purpose: This exercise teaches you how to handle “Arrays of Pointers.” Instead of moving large chunks of string data in memory, you simply swap the pointers (memory addresses), which is much faster.
Given Input: Strings: "Zebra", "Apple", "Mango"
Expected Output:
Before: Zebra, Apple, Mango
After: Apple, Mango, Zebra
+ Hint
Use an array of pointers char *arr[]. Use strcmp(s1, s2) which returns a positive value if string 1 is alphabetically “greater” than string 2.
+ Show Solution
#include <stdio.h>
#include <string.h>
void sortStrings(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) {
char *temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
char *fruits[] = {"Zebra", "Apple", "Mango"};
printf("Before: Zebra, Apple, Mango\n");
sortStrings(fruits, 3);
printf("After: %s, %s, %s\n", fruits[0], fruits[1], fruits[2]);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
char *temp: Notice we are swappingchar*(pointers), not the actual characters. We are just rearranging the “labels” pointing to the words.strcmp: This function compares ASCII values character by character. “Apple” is less than “Zebra” because ‘A’ (65) is less than ‘Z’ (90).- Efficiency: Swapping pointers takes the same amount of time regardless of how long the strings are (e.g., swapping pointers to “A” vs “Antidisestablishmentarianism”).
Exercise 38: Longest Word in a Sentence
Practice Problem: Write a program that identifies the longest word in a given sentence. If multiple words have the same maximum length, return the first one found.
Exercise Purpose: This combines string traversal with logic for tracking “local maxima.” It teaches how to use pointers to mark the start of a substring and calculate its length on the fly.
Given Input: Sentence: "I am learning Programming"
Expected Output:
Sentence: I am learning Programming
Longest Word: Programming
+ Hint
+ Show Solution
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char str[] = "I am learning Programming";
int maxLen = 0, currLen = 0, startIdx = 0, maxStart = 0;
for (int i = 0; i <= strlen(str); i++) {
if (isspace(str[i]) || str[i] == '\0') {
if (currLen > maxLen) {
maxLen = currLen;
maxStart = startIdx;
}
currLen = 0;
startIdx = i + 1;
} else {
currLen++;
}
}
printf("Sentence: %s\n", str);
printf("Longest Word: ");
for (int i = maxStart; i < maxStart + maxLen; i++) printf("%c", str[i]);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
isspaceor\0: This identifies the boundary of a word. When a boundary is hit, the program evaluates the word just finished.maxStart = startIdx: We store the index where the longest word began so we can print it later.currLen: This resets to 0 every time a space is encountered, beginning the count for a new word.
Exercise 39: Pascal’s Triangle
Practice Problem: Write a program to generate the first 5 rows of Pascal’s Triangle. Each number is the sum of the two numbers directly above it.
Exercise Purpose: This exercise teaches 2D array logic and combinatorial math. It is excellent for understanding how to use values from a previous state (the previous row) to calculate the current state.
Given Input: Rows: 5
Expected Output:
Pascal's Triangle (5 rows):
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
+ Hint
- Use a 2D array where
arr[i][j] = arr[i-1][j-1] + arr[i-1][j]. - The edges of the triangle (where
j=0orj=i) are always1.
+ Show Solution
#include <stdio.h>
int main() {
int rows = 5, arr[5][5];
printf("Pascal's Triangle (5 rows):\n");
for (int i = 0; i < rows; i++) {
// Print spaces for triangle shape
for (int s = 0; s < rows - i; s++) printf(" ");
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i)
arr[i][j] = 1;
else
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
arr[i][j] = arr[i-1][j-1] + arr[i-1][j]: This is the core Pascal logic. It looks at the row above (i-1) and adds the elements from the left and right positions.- Inner Loop
j <= i: In row 0, we print 1 item; in row 1, we print 2 items, and so on. This creates the triangular structure. - Formatting: The
rows - iloop prints leading spaces so the output looks like a centered pyramid rather than a left-aligned block.
Exercise 40: Hollow Triangle Pattern
Practice Problem: Write a program to print a hollow triangle pattern using stars (*). The triangle should have a solid base, but the interior should be empty.
Exercise Purpose: This exercise sharpens your logic regarding nested loops and conditional boundaries. You learn how to identify specific coordinates in a grid (the edges) while ignoring the “inner” coordinates.
Given Input: Height: 5 rows
Expected Output:
Generating Hollow Triangle (Height 5):
*
* *
* *
* *
*********
+ Hint
A star should only be printed if it is on the first column of a row, the last column of a row (j == i), or if it is the very last row. Otherwise, print a space.
+ Show Solution
#include <stdio.h>
int main() {
int rows = 5;
printf("Generating Hollow Triangle (Height %d):\n", rows);
for (int i = 1; i <= rows; i++) {
// Print leading spaces for alignment
for (int j = i; j < rows; j++) printf(" ");
for (int j = 1; j <= (2 * i - 1); j++) {
// Print star only at boundaries or the last row
if (j == 1 || j == (2 * i - 1) || i == rows) {
printf("*");
} else {
printf(" ");
}
}
printf("\n");
}
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
j == 1 || j == (2 * i - 1): This checks if the current position is the very first or very last star of the current row.i == rows: This condition ensures that the bottom row is printed as a solid line of stars.2 * i - 1: This formula determines the total width of the triangle at any given row $i$ to keep it centered.
Exercise 41: Solid Diamond Pattern
Practice Problem: Write a program to print a solid diamond pattern. The program should handle the “growth” phase (top triangle) and the “shrink” phase (inverted triangle).
Exercise Purpose: This teaches you how to manage multiple loop structures that depend on the same variable. It is a great exercise for understanding symmetry in algorithms.
Given Input: Maximum Width: 9 stars (at the center)
Expected Output:
Generating Solid Diamond (Max Width 9):
*
***
*****
*******
*********
*******
*****
***
*
+ Hint
- Split the problem into two parts.
- The first part increases stars from 1 to N
- The second part decreases stars from N-1 back to 1.
+ Show Solution
#include <stdio.h>
int main() {
int n = 5; // Half of diamond height
printf("Generating Solid Diamond (Max Width %d):\n", 2*n-1);
// Top half
for (int i = 1; i <= n; i++) {
for (int j = i; j < n; j++) printf(" ");
for (int j = 1; j <= (2 * i - 1); j++) printf("*");
printf("\n");
}
// Bottom half
for (int i = n - 1; i >= 1; i--) {
for (int j = n; j > i; j--) printf(" ");
for (int j = 1; j <= (2 * i - 1); j++) printf("*");
printf("\n");
}
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
- Two Main Loops: The first
forloop handles the upper triangle. The secondforloop is mirrored but starts fromn-1to avoid repeating the center line. 2 * i - 1: This ensures an odd number of stars in every row, which is required for a centered, symmetrical diamond.
Exercise 42: Alternating Positive and Negative Order
Practice Problem: Given an array containing both positive and negative integers, rearrange them so that they alternate (e.g., Positive, Negative, Positive…). Do not use an extra array.
Exercise Purpose: This is an “In-Place” rearrangement problem. It teaches you how to swap elements based on index parity (even/odd) and search for the next available element that fits a specific criterion.
Given Input: Array: {-1, 2, -3, 4, 5, 6, -7, 8, 9}
Expected Output:
Original: -1, 2, -3, 4, 5, 6, -7, 8, 9
Rearranged: 2 -1 4 -3 5 -7 6 8 9
+ Hint
Iterate through the array. If an even index has a negative number, or an odd index has a positive number, find the next number of the opposite sign and swap them.
+ Show Solution
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a; *a = *b; *b = temp;
}
int main() {
int arr[] = {-1, 2, -3, 4, 5, 6, -7, 8, 9};
int n = 9;
printf("Original: -1, 2, -3, 4, 5, 6, -7, 8, 9\n");
for (int i = 0; i < n; i++) {
// If index is even, we want a positive number
if (i % 2 == 0 && arr[i] < 0) {
for (int j = i + 1; j < n; j++) {
if (arr[j] >= 0) { swap(&arr[i], &arr[j]); break; }
}
}
// If index is odd, we want a negative number
else if (i % 2 != 0 && arr[i] >= 0) {
for (int j = i + 1; j < n; j++) {
if (arr[j] < 0) { swap(&arr[i], &arr[j]); break; }
}
}
}
printf("Rearranged: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
i % 2 == 0: We use the modulo operator to determine if the current “slot” should be positive or negative.- Nested Search: When a “wrong” sign is found at index
i, the inner loop searches the rest of the array for a “correct” sign to swap in. - In-Place: No extra memory is used; we only shift existing data within the array bounds.
Exercise 43: File Stats (Lines, Words, Characters)
Practice Problem: Write a program to read a text file and count three things: the total number of characters, the total number of words, and the total number of lines.
Exercise Purpose: This exercise is essentially building a simplified version of the Unix wc (word count) utility. It teaches state management within file streams.
Given Input:
- File
stats.txtwith:Hello WorldLearning C is fun
Expected Output:
Characters: 29 | Words: 6 | Lines: 1
+ Hint
- Characters are counted on every
fgetc. Lines are counted on\n. - Words are counted when you transition from a space to a non-space character.
+ Show Solution
#include <stdio.h>
#include <ctype.h>
int main() {
FILE *fptr = fopen("stats.txt", "r");
if (!fptr) return 1;
int chars = 0, words = 0, lines = 0, in_word = 0;
char ch;
while ((ch = fgetc(fptr)) != EOF) {
chars++;
if (ch == '\n') lines++;
if (isspace(ch)) {
in_word = 0;
} else if (in_word == 0) {
in_word = 1;
words++;
}
}
printf("Characters: %d | Words: %d | Lines: %d\n", chars, words, lines + 1);
fclose(fptr);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
in_wordFlag: This prevents double-counting words when there are multiple spaces. We only incrementwordswhen we hit the start of a word.lines + 1: Since the last line might not end with a\n, we add 1 to the final line count to account for the content on the final line.
Exercise 44: Middle Element of a Linked List
Practice Problem: Implement a function that finds the middle element of a linked list in a single traversal using the “Slow and Fast Pointer” technique. Note: You need to create struct Node with int data and pointer to next node.
Exercise Purpose: This is a classic coding interview problem. It demonstrates how multiple pointers moving at different speeds can solve geometric problems in a data structure without knowing its total size.
Given Input:
- List:
1 -> 2 -> 3 -> 4 -> 5 -> NULL
Expected Output:
List: 1 -> 2 -> 3 -> 4 -> 5
Middle Element: 3
+ Hint
- Use two pointers,
slowandfast. - For every one step the
slowpointer takes, thefastpointer takes two. - When
fastreaches the end,slowwill be exactly at the middle.
+ Show Solution
#include <stdio.h>
#include <stdlib.h>
struct Node { int data; struct Node *next; };
void findMiddle(struct Node *head) {
struct Node *slow = head, *fast = head;
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next; // Move 2 steps
slow = slow->next; // Move 1 step
}
printf("Middle Element: %d\n", slow->data);
}
int main() {
struct Node *n5 = malloc(sizeof(struct Node)), *n4 = malloc(sizeof(struct Node)),
*n3 = malloc(sizeof(struct Node)), *n2 = malloc(sizeof(struct Node)),
*n1 = malloc(sizeof(struct Node));
n1->data = 1; n1->next = n2; n2->data = 2; n2->next = n3;
n3->data = 3; n3->next = n4; n4->data = 4; n4->next = n5;
n5->data = 5; n5->next = NULL;
printf("List: 1 -> 2 -> 3 -> 4 -> 5\n");
findMiddle(n1);
return 0;
}Code language: C++ (cpp)
Explanation of Solution:
fast = fast->next->next: Because the fast pointer moves double the speed, it reaches the “finish line” twice as fast as the slow pointer.- Relative Distance: Because the finish line for
fastis the end of the list ($L$), theslowpointer will have covered exactly $L/2$ distance. - Loop Condition: We check both
fastandfast->nextto ensure we don’t crash when jumping two nodes at a time in both even and odd-lengthed lists.

Leave a Reply