Structures and Unions are the two fundamental concepts are crucial for organizing complex data, managing memory efficiently, and building sophisticated applications like linked lists, file systems, and databases.
This guide provides 20+ Structures and Unions coding exercises designed to solidify your understanding.
Each exercise includes a Practice Problem, Hint, Solution code, and detailed Explanation, ensuring you don’t just copy code, but genuinely understand how and why it works.
Also, See: C Programming Exercises with 9 topic-wise sets and 275+ practice questions.
What You’ll Practice
The challenges cover the following key topics:
- Structure Fundamentals: Defining, initializing, and accessing members
- Organization: Creating Arrays of Structures, implementing Nested Structures, and using Enums for defining constants.
- Memory Efficiency: Defining and utilizing Unions and implementing Bit Fields for minimal memory usage.
- Application: Passing structures to Functions, performing Binary File I/O (fread, fwrite), and using Pointers to Structures.
Use Online C Compiler to solve exercises.
+ Table Of Contents (22 Exercises)
Table of contents
- Exercise 1: Define and Display a Student Structure
- Exercise 2: Structure Initialization at Declaration
- Exercise 3: Finding the Highest Percentage
- Exercise 4: Nested Structure (Structure within a Structure)
- Exercise 5: Passing Structure to a Function
- Exercise 6: Returning Structure from a Function
- Exercise 7: Pointers to Structures
- Exercise 8: Comparing Structures
- Exercise 9: Self-Referential Structure (Basic Node)
- Exercise 10: Dynamic Memory Allocation for Structure
- Exercise 11: Basic Union
- Exercise 12: Structure vs. Union Size
- Exercise 13: Union with Struct Member (Conceptual)
- Exercise 14: Enumeration (Enum) Basic
- Exercise 15: Enum in Structure
- Exercise 16: Function Pointers in Structures
- Exercise 17: Bit Fields
- Exercise 18: Searching in an Array of Structures
- Exercise 19: Merging Structures (Data Consolidation)
- Exercise 20: Passing Array of Structures to a Function
- Exercise 21: Complex Number Structure (Addition)
- Exercise 22: Simple Inventory Management (Application)
Exercise 1: Define and Display a Student Structure
Practice Problem: Define a structure named Student with members for their name (string), roll_number (integer), and percentage (float). Write a C program to input the details for one student and then display those details.
Expected Output:
Enter Student Name: Jessa
Enter Roll Number: 25
Enter Percentage: 85
--- Student Details ---
Name: Jessa
Roll Number: 25
Percentage: 85.00%
+ Hint
Use the dot operator (.) to access the members of the structure variable. Use scanf("%s", ...) for the name, but be careful with strings and spaces. fgets is often safer for strings, but for simplicity here, stick to basic scanf.
+ Show Solution
#include <stdio.h>
// 1. Structure Definition
struct Student {
char name[50];
int roll_number;
float percentage;
};
int main() {
// 2. Declare a structure variable
struct Student s1;
// 3. Input details
printf("Enter Student Name: ");
scanf("%s", s1.name); // Note: scanf stops reading at the first whitespace
printf("Enter Roll Number: ");
scanf("%d", &s1.roll_number);
printf("Enter Percentage: ");
scanf("%f", &s1.percentage);
// 4. Display details
printf("\n--- Student Details ---\n");
printf("Name: %s\n", s1.name);
printf("Roll Number: %d\n", s1.roll_number);
printf("Percentage: %.2f%%\n", s1.percentage);
return 0;
}Code language: C++ (cpp)
Explanation:
- The program first defines the
Studentstructure template. Inmain(), a variables1of this structure type is created, reserving memory for all three members contiguously. - The input process uses the dot operator (
s1.name,s1.roll_number, etc.) to directly access and assign values to the individual fields of thes1variable. The output simply retrieves and prints these stored values.
Exercise 2: Structure Initialization at Declaration
Practice Problem: Define a Book structure with members: title (string), author (string), pages (integer), and price (float). Declare a structure variable and initialize all its members at the time of declaration using an initializer list. Finally, display all the initialized details.
Expected Output:
--- Book Details ---
Title: The C Programming Language
Author: Dennis Ritchie
Pages: 272
Price: $12.50
+ Hint
Structure initialization uses curly braces {} immediately following the variable name during declaration. The values must be listed in the order the members are defined in the structure.
+ Show Solution
#include <stdio.h>
// 1. Structure Definition
struct Book {
char title[100];
char author[50];
int pages;
float price;
};
int main() {
// 2. Declaration and Initialization
struct Book b1 = {
"The C Programming Language",
"Dennis Ritchie",
272,
12.50
};
// 3. Display details
printf("--- Book Details ---\n");
printf("Title: %s\n", b1.title);
printf("Author: %s\n", b1.author);
printf("Pages: %d\n", b1.pages);
printf("Price: $ %.2f\n", b1.price);
return 0;
}Code language: C++ (cpp)
Explanation:
- The structure variable
b1of typestruct Bookis declared. By placing an equals sign (=) followed by values enclosed in braces ({...}), we perform a designated initialization. - The compiler assigns “The C Programming Language” to
b1.title, “Dennis Ritchie” tob1.author, and so on, in the defined order. This is a static, clean way to set initial values.
Exercise 3: Finding the Highest Percentage
Practice Problem: Create an array of 3 Student structures (using the definition from Exercise 1). Input data for all 3 students. Then, iterate through the array to find and display the details of the student who has the highest percentage.
Expected Output:
Enter details for Student 1:
Name: Jessa
Roll Number: 25
Percentage: 85
Enter details for Student 2:
Name: Jon
Roll Number: 26
Percentage: 76
Enter details for Student 3:
Name: Gopal
Roll Number: 27
Percentage: 84
--- Student with Highest Percentage ---
Name: Jessa
Percentage: 85.00%
+ Hint
Declare the array as struct Student students[3];. Use a for loop to input data and a separate for loop to compare percentages, keeping track of the index of the student with the current maximum percentage found so far.
+ Show Solution
#include <stdio.h>
struct Student {
char name[50];
int roll_number;
float percentage;
};
int main() {
// 1. Declare array of structures
struct Student students[3];
int i;
int max_index = 0; // Index of the student with the highest percentage
// 2. Input data for 5 students
for (i = 0; i < 3; i++) {
printf("\nEnter details for Student %d:\n", i + 1);
printf("Name: ");
scanf("%s", students[i].name);
printf("Roll Number: ");
scanf("%d", &students[i].roll_number);
printf("Percentage: ");
scanf("%f", &students[i].percentage);
}
// 3. Find the student with the highest percentage
for (i = 1; i < 3; i++) {
if (students[i].percentage > students[max_index].percentage) {
max_index = i; // Update the index if a higher percentage is found
}
}
// 4. Display the highest-scoring student's details
printf("\n--- Student with Highest Percentage ---\n");
printf("Name: %s\n", students[max_index].name);
printf("Percentage: %.2f%%\n", students[max_index].percentage);
return 0;
}Code language: C++ (cpp)
Explanation:
- The declaration
struct Student students[3];creates an array where each element is an entireStudentstructure. - The first loop handles input, accessing each element using
students[i].member. The second loop iterates through the array, comparingstudents[i].percentagewith the percentage atstudents[max_index]. - If a higher value is found,
max_indexis updated. Finally, the details of the student at the storedmax_indexare printed.
Exercise 4: Nested Structure (Structure within a Structure)
Practice Problem: Define a structure Date (members: day, month, year). Define another structure Employee (members: id, name, and an instance of the Date structure called joining_date). Input and display the employee’s ID, name, and joining date.
Expected Output:
Enter Employee ID: 1
Enter Employee Name: Jessa
Enter Joining Day (DD): 10
Enter Joining Month (MM): 6
Enter Joining Year (YYYY): 2024
--- Employee Details ---
ID: 1
Name: Jessa
Joining Date: 10/6/2024
+ Hint
When accessing the day member, you’ll need to chain the dot operators: employee_var.joining_date.day.
+ Show Solution
#include <stdio.h>
// 1. Inner Structure Definition
struct Date {
int day;
int month;
int year;
};
// 2. Outer Structure Definition (Nested Structure)
struct Employee {
int id;
char name[50];
struct Date joining_date; // Instance of Date structure
};
int main() {
struct Employee emp1;
// 3. Input Employee Details
printf("Enter Employee ID: ");
scanf("%d", &emp1.id);
printf("Enter Employee Name: ");
scanf("%s", emp1.name);
// 4. Input Nested Date Details
printf("Enter Joining Day (DD): ");
scanf("%d", &emp1.joining_date.day);
printf("Enter Joining Month (MM): ");
scanf("%d", &emp1.joining_date.month);
printf("Enter Joining Year (YYYY): ");
scanf("%d", &emp1.joining_date.year);
// 5. Display Details
printf("\n--- Employee Details ---\n");
printf("ID: %d\n", emp1.id);
printf("Name: %s\n", emp1.name);
printf("Joining Date: %d/%d/%d\n",
emp1.joining_date.day,
emp1.joining_date.month,
emp1.joining_date.year);
return 0;
}Code language: C++ (cpp)
Explanation:
- The
Employeestructure is defined to include an entire instance of theDatestructure, making it a nested structure. - To access a field within the inner structure (like
day), you must traverse through the outer structure variable (emp1) and the inner structure member (joining_date) using successive dot operators (emp1.joining_date.day).
Exercise 5: Passing Structure to a Function
Practice Problem: Define a Rectangle structure (members: length, width). Write a function, calculate_properties, that accepts a Rectangle structure as an argument. Inside the function, calculate the area (L×W) and perimeter (2×(L+W)) of the rectangle and print these results directly.
Expected Output:
Enter Length of Rectangle: 10
Enter Width of Rectangle: 5
--- Calculation Results ---
Length: 10.00, Width: 5.00
Area: 50.00
Perimeter: 30.00
+ Hint
The function signature should look like void calculate_properties(struct Rectangle r). Since you are printing the results inside the function, the function’s return type can be void. Use the dot operator (.) to access the members within the function.
+ Show Solution
#include <stdio.h>
// 1. Structure Definition
struct Rectangle {
float length;
float width;
};
// 2. Function to calculate and print properties (Pass by Value)
void calculate_properties(struct Rectangle r) {
float area = r.length * r.width;
float perimeter = 2 * (r.length + r.width);
printf("\n--- Calculation Results ---\n");
printf("Length: %.2f, Width: %.2f\n", r.length, r.width);
printf("Area: %.2f\n", area);
printf("Perimeter: %.2f\n", perimeter);
}
int main() {
struct Rectangle rect1;
printf("Enter Length of Rectangle: ");
scanf("%f", &rect1.length);
printf("Enter Width of Rectangle: ");
scanf("%f", &rect1.width);
// 3. Pass the entire structure rect1 to the function
calculate_properties(rect1);
return 0;
}Code language: C++ (cpp)
Explanation:
- The structure
rect1is passed to the functioncalculate_propertiesusing pass-by-value. This means a complete copy of the structure’s data (lengthandwidth) is made and stored in the function’s local variabler. - The function uses this local copy to perform the simple arithmetic calculations for area and perimeter. Because the function’s primary job is to print the results, it is defined with a
voidreturn type. The original structurerect1inmainremains unchanged.
Exercise 6: Returning Structure from a Function
Practice Problem: Define a Rectangle structure (members: length, width, area). Write a function, get_rectangle_data, that prompts the user for the length and width, calculates the area, and returns the complete Rectangle structure back to the calling function (main).
Expected Output:
Enter Length of Rectangle: 10
Enter Width of Rectangle: 5
--- Rectangle Report ---
Length: 10.00
Width: 5.00
Calculated Area: 50.00
+ Hint
The function’s return type must be the structure itself: struct Rectangle get_rectangle_data(). In main, assign the function’s result to a structure variable: r1 = get_rectangle_data();.
+ Show Solution
#include <stdio.h>
// 1. Structure Definition
struct Rectangle {
float length;
float width;
float area;
};
// 2. Function that returns a structure
struct Rectangle get_rectangle_data() {
struct Rectangle r;
printf("Enter Length of Rectangle: ");
scanf("%f", &r.length);
printf("Enter Width of Rectangle: ");
scanf("%f", &r.width);
// Calculate Area
r.area = r.length * r.width;
return r; // Returns the entire structure
}
int main() {
// 3. Call the function and store the returned structure
struct Rectangle r1 = get_rectangle_data();
printf("\n--- Rectangle Report ---\n");
printf("Length: %.2f\n", r1.length);
printf("Width: %.2f\n", r1.width);
printf("Calculated Area: %.2f\n", r1.area);
return 0;
}Code language: C++ (cpp)
Explanation:
- The function
get_rectangle_datais declared to return a value of typestruct Rectangle. Inside the function, a localstruct Rectanglevariableris populated. - The statement
return r;copies the entire content of the local structurerback to the calling function (main). Inmain, the returned structure copy is stored in the variabler1, and its members are then accessed and displayed.
Exercise 7: Pointers to Structures
Practice Problem: Define a Car structure (members: model_year, color). Declare a variable of this structure and a pointer to this structure. Use the structure pointer to: 1) assign values to the members, and 2) print the assigned values.
Expected Output:
Enter Car Model Year: 2024
Enter Car Color: Red
--- Car Details (via Pointer) ---
Model Year: 2024
Color: Red
+ Hint
When accessing members using a structure pointer, you must use the arrow operator (->) instead of the dot operator (.). Also, the pointer must be assigned the address of the structure variable (ptr = &car_var;).
+ Show Solution
#include <stdio.h>
// 1. Structure Definition
struct Car {
int model_year;
char color[20];
};
int main() {
// 2. Declare a structure variable
struct Car my_car;
// 3. Declare a pointer to the structure
struct Car *car_ptr;
// 4. Point the pointer to the structure variable
car_ptr = &my_car;
// 5. Access and assign values using the arrow operator (->)
printf("Enter Car Model Year: ");
scanf("%d", &car_ptr->model_year);
printf("Enter Car Color: ");
scanf("%s", car_ptr->color);
// 6. Access and display values using the arrow operator
printf("\n--- Car Details (via Pointer) ---\n");
printf("Model Year: %d\n", car_ptr->model_year);
printf("Color: %s\n", car_ptr->color);
return 0;
}Code language: C++ (cpp)
Explanation:
car_ptris a pointer designed to hold the memory address of astruct Car.- By assigning
car_ptr = &my_car;, it points to themy_carvariable. - The arrow operator (
->) is syntactical shorthand for dereferencing the pointer and then accessing a member. For example,car_ptr->model_yearis equivalent to(*car_ptr).model_year. This is the standard way to interact with structures via pointers.
Exercise 8: Comparing Structures
Practice Problem: Define a Time structure (members: hour, minute, second). Write a program that declares two Time structure variables, inputs data for both, and then uses a function to check if the two times are exactly the same.
Expected Output:
Enter Time 1 (HH MM SS): 12 45 50
Enter Time 2 (HH MM SS): 12 45 50
Both Time structures represent the SAME time.
+ Hint
The comparison function should accept two struct Time variables. It must check for equality on all three members (hour, minute, AND second) simultaneously. The function should return 1 (true) if they are equal, and 0 (false) otherwise.
+ Show Solution
#include <stdio.h>
// 1. Structure Definition
struct Time {
int hour;
int minute;
int second;
};
// 2. Comparison function
int compare_times(struct Time t1, struct Time t2) {
if (t1.hour == t2.hour &&
t1.minute == t2.minute &&
t1.second == t2.second) {
return 1; // Times are identical
} else {
return 0; // Times are different
}
}
int main() {
struct Time time1, time2;
printf("Enter Time 1 (HH MM SS): ");
scanf("%d %d %d", &time1.hour, &time1.minute, &time1.second);
printf("Enter Time 2 (HH MM SS): ");
scanf("%d %d %d", &time2.hour, &time2.minute, &time2.second);
// 3. Call comparison function
if (compare_times(time1, time2)) {
printf("\nBoth Time structures represent the SAME time.\n");
} else {
printf("\nThe two Time structures represent DIFFERENT times.\n");
}
return 0;
}Code language: C++ (cpp)
Explanation:
- C does not allow direct comparison of two structures using the equality operator (
==) likeif (time1 == time2). - Therefore, we must define a function,
compare_times, that explicitly checks the equality of each corresponding member using the logical AND operator (&&). If all three conditions are true, the function returns 1, confirming the structures are logically equal in value.
Exercise 9: Self-Referential Structure (Basic Node)
Practice Problem: Define a self-referential structure called Node. It should have an integer data member (data) and a pointer (next) that points to a structure of the same type (struct Node). Create two nodes, assign data to them, and link the first node to the second. Display the data from both nodes by starting only from the first node.
Given:
// 1. Self-Referential Structure Definition
struct Node {
int data;
struct Node *next; // Pointer to a structure of type Node
};Code language: C++ (cpp)
Expected Output:
Node 1 Data: 100
Node 2 Data (via n1 pointer): 200
+ Hint
The structure definition should look like: struct Node { int data; struct Node *next; };. To link them, set the pointer of the first node to the address of the second node: n1.next = &n2;.
+ Show Solution
#include <stdio.h>
// 1. Self-Referential Structure Definition
struct Node {
int data;
struct Node *next; // Pointer to a structure of type Node
};
int main() {
// 2. Create two structure variables (nodes)
struct Node n1, n2;
// 3. Assign data to nodes
n1.data = 100;
n2.data = 200;
// 4. Link the first node to the second
n1.next = &n2; // n1's pointer now holds the address of n2
// 5. Set the second node's pointer to NULL (end of the list)
n2.next = NULL;
// 6. Access and display data starting only from n1
printf("Node 1 Data: %d\n", n1.data);
printf("Node 2 Data (via n1 pointer): %d\n", n1.next->data);
return 0;
}Code language: C++ (cpp)
Explanation:
- A self-referential structure is one that contains a pointer to itself. This is the fundamental building block for data structures like Linked Lists.
- We create
n1andn2. The linen1.next = &n2;establishes the link, allowing us to navigate fromn1ton2. The expressionn1.next->datauses the pointer stored inn1.nextto access thedatamember of the node it points to (which isn2).
Exercise 10: Dynamic Memory Allocation for Structure
Practice Problem: Define a Circle structure (members: radius and area). Use the malloc() function to dynamically allocate memory for a single Circle structure. Assign a radius, calculate the area (πr2), and display the results. Remember to free the allocated memory.
Given:
// 1. Structure Definition
struct Circle {
float radius;
float area;
};Code language: C++ (cpp)
Expected Output:
Enter Circle Radius: 5
--- Dynamic Circle Report ---
Radius: 5.00
Area: 78.54
+ Hint
You’ll need \#include <stdlib.h> and \#include <math.h>. The allocation is done via struct Circle *c_ptr = (struct Circle *)malloc(sizeof(struct Circle));. Access members using the arrow operator (->) and use free(c_ptr) at the end. Use M_PI from <math.h> for π.
+ Show Solution
#include <stdio.h>
#include <stdlib.h> // for malloc and free
#include <math.h> // for M_PI (pi constant)
// 1. Structure Definition
struct Circle {
float radius;
float area;
};
int main() {
// 2. Dynamically allocate memory for one Circle structure
struct Circle *c_ptr = (struct Circle *)malloc(sizeof(struct Circle));
// Check if allocation was successful
if (c_ptr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
// 3. Assign data and calculate area using pointer
printf("Enter Circle Radius: ");
scanf("%f", &c_ptr->radius);
// Area = PI * r * r
c_ptr->area = M_PI * c_ptr->radius * c_ptr->radius;
// 4. Display results
printf("\n--- Dynamic Circle Report ---\n");
printf("Radius: %.2f\n", c_ptr->radius);
printf("Area: %.2f\n", c_ptr->area);
// 5. Free the allocated memory
free(c_ptr);
c_ptr = NULL; // Good practice to set pointer to NULL after freeing
return 0;
}Code language: C++ (cpp)
Explanation:
- The
malloc()function reserves a block of memory equal to the size ofstruct Circleat runtime and returns a generic pointer (void *). This is cast tostruct Circle *and stored inc_ptr. - Since
c_ptris a pointer, all member access must be done using the arrow operator (->). Finally,free(c_ptr)releases the memory back to the operating system, preventing a memory leak.
Exercise 11: Basic Union
Practice Problem: Define a Union called Data that can hold an integer (i), a float (f), or a character array (str[20]). Write a program to:
- Assign a value to the integer member (
i) and print it. - Immediately assign a value to the float member (
f) and print it. - Print the value of the integer member (
i) again to demonstrate data overwriting.
Expected Output:
After assigning d.i = 10:
d.i = 10
Size of union: 20 bytes
After assigning d.f = 250.75:
d.f = 250.75
Printing d.i again: 1132118016 (This is a corrupted or unintended data)
+ Hint
The key feature of a union is that all members share the same memory location. When one member is written, it may overwrite the data stored by a previous member. Use sizeof(union Data) to confirm its size.
+ Show Solution
#include <stdio.h>
// 1. Union Definition
union Data {
int i;
float f;
char str[20];
};
int main() {
union Data d;
// 2. Assign to integer and display
d.i = 10;
printf("After assigning d.i = 10:\n");
printf("d.i = %d\n", d.i);
printf("Size of union: %zu bytes\n", sizeof(union Data));
// 3. Assign to float (this overwrites the integer data)
d.f = 250.75;
printf("\nAfter assigning d.f = 250.75:\n");
printf("d.f = %.2f\n", d.f);
// 4. Print d.i again (will show corrupted or unintended data)
printf("\nPrinting d.i again: %d\n", d.i); // Output is meaningless
return 0;
}Code language: C++ (cpp)
Explanation:
- The
union Datareserves memory sufficient only for its largest member (which isstr[20], likely 20 bytes). - When
d.i = 10is executed, 10 is stored in that shared memory. Whend.f = 250.75is executed next, the 4 bytes used for the float member overwrite the 4 bytes previously used for the integer. - Attempting to read
d.iafterward returns the bits from the float, interpreted incorrectly as an integer, demonstrating that only one member is actively valid at any time.
Exercise 12: Structure vs. Union Size
Practice Problem: Define a structure TestStruct and a union TestUnion, both containing the exact same members: char c, int i, and float f. Write a program to use the sizeof operator to display the memory size occupied by both the structure and the union.
Expected Output:
Size of 'char' (typically 1 byte)
Size of 'int' (typically 4 bytes)
Size of 'float' (typically 4 bytes)
----------------------------------
Size of Structure (Struct): 12 bytes
Size of Union (Union): 4 bytes
+ Hint
Use the sizeof operator on the structure type and the union type directly: sizeof(struct TestStruct) and sizeof(union TestUnion). Remember that structure size often includes padding.
+ Show Solution
#include <stdio.h>
// 1. Define Structure
struct TestStruct {
char c;
int i;
float f;
};
// 2. Define Union
union TestUnion {
char c;
int i;
float f;
};
int main() {
printf("Size of 'char' (typically 1 byte)\n");
printf("Size of 'int' (typically 4 bytes)\n");
printf("Size of 'float' (typically 4 bytes)\n");
printf("\n----------------------------------\n");
// 3. Calculate and display sizes
printf("Size of Structure (Struct): %zu bytes\n", sizeof(struct TestStruct));
printf("Size of Union (Union): %zu bytes\n", sizeof(union TestUnion));
return 0;
}Code language: C++ (cpp)
Explanation:
Structure Size: The structure requires memory for all its members, one after the other. Due to memory alignment (padding), the size often exceeds the sum of the member sizes (1+4+4=9 bytes). The compiler adds padding so that the int and float (which typically need to start on an address divisible by 4) are correctly aligned. The total size here will likely be 12 bytes (1 byte for char, 3 bytes padding, 4 bytes for int, 4 bytes for float).
Union Size: The union requires memory only for its largest member (here, the int or float at 4 bytes, or 4 bytes if the largest is 4 bytes). The union size is 4 bytes (assuming standard sizes), as all members share the same starting address.
Exercise 13: Union with Struct Member (Conceptual)
Practice Problem: Define a structure Asset with an integer id and a character array type (‘C’ for Car, ‘P’ for Property). Define a union Details that holds specific information: char car_license[10] or int property_id. Create an Asset variable that includes the Details union as a member. Input and display data for an asset, showing only the relevant union member based on the asset type.
Given:
// 1. Define the Union
union Details {
char car_license[10];
int property_id;
};
// 2. Define the Structure containing the Union
struct Asset {
int id;
char type; // 'C' or 'P'
union Details info;
};Code language: C++ (cpp)
Expected Output:
Enter Asset ID: 10
Enter Asset Type (C/P): C
Enter Car License Plate: NY123
--- Asset Report ---
Asset ID: 10
Type: Car, License: NY123
+ Hint
Use an if/else condition to decide which member of the union to read or write. The union must be embedded within the structure: struct Asset { ... union Details info; };.
+ Show Solution
#include <stdio.h>
#include <string.h>
// 1. Define the Union
union Details {
char car_license[10];
int property_id;
};
// 2. Define the Structure containing the Union
struct Asset {
int id;
char type; // 'C' or 'P'
union Details info;
};
int main() {
struct Asset a1;
printf("Enter Asset ID: ");
scanf("%d", &a1.id);
printf("Enter Asset Type (C/P): ");
scanf(" %c", &a1.type); // Note the space before %c to clear newline
if (a1.type == 'C' || a1.type == 'c') {
printf("Enter Car License Plate: ");
scanf("%s", a1.info.car_license);
} else if (a1.type == 'P' || a1.type == 'p') {
printf("Enter Property ID Number: ");
scanf("%d", &a1.info.property_id);
}
printf("\n--- Asset Report ---\n");
printf("Asset ID: %d\n", a1.id);
// 3. Display only the relevant union member
if (a1.type == 'C' || a1.type == 'c') {
printf("Type: Car, License: %s\n", a1.info.car_license);
} else if (a1.type == 'P' || a1.type == 'p') {
printf("Type: Property, Property ID: %d\n", a1.info.property_id);
}
return 0;
}Code language: C++ (cpp)
Explanation:
- The structure
Assetacts as a tagged union (or discriminated union, conceptually) because it contains a field (type) that tells us which member of the nested union (info) is currently valid. - The memory for the
infounion is the same regardless of whether we store a license plate or a property ID. Theif/elselogic uses the structure’stypefield to safely interact with the appropriate union member, ensuring we don’t read garbage data.
Exercise 14: Enumeration (Enum) Basic
Practice Problem: Define an enumeration (enum) named DaysOfWeek containing the seven days of the week, starting from SUNDAY. Explicitly set MONDAY to start at the value 1. Print the integer value associated with each day.
Expected Output:
--- Days of the Week Values ---
SUNDAY: 0
MONDAY: 1
TUESDAY: 2
WEDNESDAY: 3
THURSDAY: 4
FRIDAY: 5
SATURDAY: 6
+ Hint
By default, enums start at 0 and increment by 1. To set a specific starting value, use the equals sign: MONDAY = 1. All subsequent members will increment from there.
+ Show Solution
#include <stdio.h>
// 1. Enum Definition with explicit start value
enum DaysOfWeek {
SUNDAY, // Default: 0
MONDAY = 1, // Explicitly set to 1
TUESDAY, // Increments from MONDAY: 2
WEDNESDAY, // 3
THURSDAY, // 4
FRIDAY, // 5
SATURDAY // 6
};
int main() {
printf("--- Days of the Week Values ---\n");
printf("SUNDAY: %d\n", SUNDAY);
printf("MONDAY: %d\n", MONDAY);
printf("TUESDAY: %d\n", TUESDAY);
printf("WEDNESDAY: %d\n", WEDNESDAY);
printf("THURSDAY: %d\n", THURSDAY);
printf("FRIDAY: %d\n", FRIDAY);
printf("SATURDAY: %d\n", SATURDAY);
// Can use enum constants in calculations
if (TUESDAY > MONDAY) {
printf("\nTUESDAY is numerically greater than MONDAY.\n");
}
return 0;
}Code language: C++ (cpp)
Explanation:
- An enumeration in C defines a set of named integer constants. By setting
MONDAY = 1, we initialize its underlying integer value.SUNDAYtakes the default preceding value (0). - All constants that follow (
TUESDAY,WEDNESDAY, etc.) automatically increment by one from the last assigned value. Enums improve code readability by replacing “magic numbers” (like 0, 1, 2…) with meaningful names.
Exercise 15: Enum in Structure
Practice Problem: Define an enum for Color (RED, GREEN, BLUE). Define a Product structure with members: name (string), price (float), and an instance of the Color enumeration called product_color. Input and display the details of a product, using the enum to assign and display the color.
Expected Output:
--- Product Details ---
Name: T-Shirt
Price: $19.99
Color (Value): 1
Color (Name): GREEN
+ Hint
You can assign the enum constant directly to the structure member: p1.product_color = GREEN;. Use a switch statement when displaying the color to convert the integer enum value back into its readable string name.
+ Show Solution
#include <stdio.h>
#include <string.h>
// 1. Enum Definition
enum Color {
RED, // 0
GREEN, // 1
BLUE // 2
};
// 2. Structure Definition using the Enum
struct Product {
char name[50];
float price;
enum Color product_color; // Using the enum type
};
void display_color(enum Color c) {
switch (c) {
case RED: printf("RED"); break;
case GREEN: printf("GREEN"); break;
case BLUE: printf("BLUE"); break;
default: printf("UNKNOWN"); break;
}
}
int main() {
struct Product p1;
// 3. Input Data
strcpy(p1.name, "T-Shirt");
p1.price = 19.99;
// Assign the color using the enum constant
p1.product_color = GREEN;
// 4. Display Data
printf("--- Product Details ---\n");
printf("Name: %s\n", p1.name);
printf("Price: $%.2f\n", p1.price);
printf("Color (Value): %d\n", p1.product_color);
printf("Color (Name): ");
display_color(p1.product_color);
printf("\n");
return 0;
}Code language: C++ (cpp)
Explanation:
- The
enum Colorprovides a clean, self-documenting way to represent colors using integer values. By makingproduct_coloranenum Colortype, the code clearly restricts the acceptable values for the color field. - We assign the symbolic name
GREEN(which is integer 1). Theswitchstatement demonstrates how to map the stored integer value back to a user-friendly string when displaying the product details.
Exercise 16: Function Pointers in Structures
Practice Problem: Define a structure Operation that contains two integer operands (op1, op2) and a function pointer (op_func) that can point to a function which takes two integers and returns an integer. Write two separate functions (add and subtract). Use the structure to set the operands and call both add and subtract using the function pointer.
Given:
// 1. Structure Definition with Function Pointer
struct Operation {
int op1;
int op2;
int (*op_func)(int, int); // Function pointer member
};Code language: C++ (cpp)
Expected Output:
Addition (50 + 15): 65
Subtraction (50 - 15): 35
+ Hint
The function pointer definition inside the structure is critical: int (*op_func)(int, int);. To call the function via the pointer, use either op.op_func(op1, op2) or (*op.op_func)(op1, op2).
+ Show Solution
#include <stdio.h>
// Function definitions
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
// 1. Structure Definition with Function Pointer
struct Operation {
int op1;
int op2;
int (*op_func)(int, int); // Function pointer member
};
int main() {
struct Operation calculator;
calculator.op1 = 50;
calculator.op2 = 15;
// 2. Point to the 'add' function
calculator.op_func = add;
int result_add = calculator.op_func(calculator.op1, calculator.op2);
printf("Addition (%d + %d): %d\n", calculator.op1, calculator.op2, result_add);
// 3. Change the pointer to point to the 'subtract' function
calculator.op_func = subtract;
int result_sub = calculator.op_func(calculator.op1, calculator.op2);
printf("Subtraction (%d - %d): %d\n", calculator.op1, calculator.op2, result_sub);
return 0;
}Code language: C++ (cpp)
Explanation:
- The function pointer
op_funcmakes theOperationstructure flexible. We can dynamically change the behavior of the structure by simply assigning a different function address (addorsubtract) to the pointer field. - This is a simple example of polymorphism (different behaviors from the same interface) and is commonly used in C for command tables or implementing callbacks.
Exercise 17: Bit Fields
Practice Problem: Define a structure Permissions to store three boolean flags: read, write, and execute. Use bit fields to ensure that each flag occupies the minimum possible memory (1 bit). Initialize an instance of this structure and display the total memory size occupied.
Expected Output:
File Permissions:
Read: 1
Write: 0
Execute: 1
Size of Permissions Structure: 4 bytes
+ Hint
Define the structure members followed by a colon and the number of bits: unsigned int read : 1;. The total size of the structure will typically be the smallest integer type that can hold all the bits (e.g., 1 byte or 4 bytes).
+ Show Solution
#include <stdio.h>
#include <stdbool.h>
// 1. Structure Definition using Bit Fields
struct Permissions {
// Each member is explicitly assigned 1 bit
unsigned int read : 1;
unsigned int write : 1;
unsigned int execute : 1;
// Padding for alignment might occur here
};
int main() {
struct Permissions file_perms;
// 2. Assign values (0 or 1)
file_perms.read = 1; // True
file_perms.write = 0; // False
file_perms.execute = 1; // True
// 3. Display values and size
printf("File Permissions:\n");
printf("Read: %d\n", file_perms.read);
printf("Write: %d\n", file_perms.write);
printf("Execute: %d\n", file_perms.execute);
// Note the potentially small size
printf("\nSize of Permissions Structure: %zu bytes\n", sizeof(struct Permissions));
return 0;
}Code language: C++ (cpp)
Explanation:
- Bit fields allow us to specify the exact width of a structure member in bits. By setting each flag to
: 1, we instruct the compiler to pack these three flags into the smallest possible memory container, typically an integer (4 bytes) or the smallest addressable unit (1 byte, if permitted). - While the total occupied memory is small (usually 4 bytes for alignment), only 3 bits are used for actual data storage, drastically saving memory when dealing with millions of such structures.
Exercise 18: Searching in an Array of Structures
Practice Problem: Define an Employee structure (id, name, salary). Create an array of 4 employees and input their details. Implement a function, search_employee, that takes the array and an ID as arguments, finds the employee with the matching ID, and prints their details. If the ID is not found, print a suitable message.
Given:
// 1. Structure Definition
struct Employee {
int id;
char name[50];
float salary;
};Code language: C++ (cpp)
Expected Output:
Enter Employee ID to search (e.g., 102): 103
--- Employee Found ---
ID: 103
Name: Charlie
Salary: $50000.00
+ Hint
The search function should iterate through the array of structures. Inside the loop, compare the input ID with the id member of the current structure element: if (arr[i].id == search_id).
+ Show Solution
#include <stdio.h>
#include <stdbool.h>
// 1. Structure Definition
struct Employee {
int id;
char name[50];
float salary;
};
// 2. Search Function
void search_employee(struct Employee employees[], int size, int search_id) {
bool found = false;
int i;
for (i = 0; i < size; i++) {
if (employees[i].id == search_id) {
printf("\n--- Employee Found ---\n");
printf("ID: %d\n", employees[i].id);
printf("Name: %s\n", employees[i].name);
printf("Salary: $%.2f\n", employees[i].salary);
found = true;
break; // Exit the loop once found
}
}
if (!found) {
printf("\nError: Employee with ID %d not found.\n", search_id);
}
}
int main() {
struct Employee staff[4] = {
{101, "Alice", 60000.00},
{102, "Bob", 75000.00},
{103, "Charlie", 50000.00},
{104, "Dana", 90000.00}
};
int search_id;
printf("Enter Employee ID to search (e.g., 102): ");
scanf("%d", &search_id);
// 3. Call the search function
search_employee(staff, 4, search_id);
return 0;
}Code language: C++ (cpp)
Explanation:
- The
search_employeefunction receives the base address of the array (employees[]), the size, and the ID to search for. When an array of structures is passed to a function, it is pass-by-reference (only the address of the first element is passed). - The function iterates through the elements. If the
idmatches thesearch_id, the details are printed, thefoundflag is set to true, and the loop breaks. If the loop completes without finding a match, the!foundcondition triggers the error message.
Exercise 19: Merging Structures (Data Consolidation)
Practice Problem: Define two structures: Personal_Info (id, address) and Job_Info (id, title, salary). Create a third structure, Full_Record (id, address, title, salary). Write a function that takes instances of Personal_Info and Job_Info (ensuring their IDs match) and returns a consolidated Full_Record structure.
Given:
struct Personal_Info {
int id;
char address[100];
};
struct Job_Info {
int id;
char title[50];
float salary;
};
// 1. Consolidated Structure
struct Full_Record {
int id;
char address[100];
char title[50];
float salary;
};Code language: C++ (cpp)
Expected Output:
--- Consolidated Employee Record ---
ID: 105
Address: 123 Main St
Title: Software Engineer
Salary: $85000.00
+ Hint
The merging function signature will be struct Full_Record merge_data(struct Personal_Info p, struct Job_Info j). Inside the function, copy the members from the input structures to the output structure.
+ Show Solution
#include <stdio.h>
#include <string.h>
struct Personal_Info {
int id;
char address[100];
};
struct Job_Info {
int id;
char title[50];
float salary;
};
// 1. Consolidated Structure
struct Full_Record {
int id;
char address[100];
char title[50];
float salary;
};
// 2. Function to merge data and return the new structure
struct Full_Record merge_data(struct Personal_Info p, struct Job_Info j) {
struct Full_Record fr;
// Assuming IDs match for merging
fr.id = p.id;
strcpy(fr.address, p.address);
strcpy(fr.title, j.title);
fr.salary = j.salary;
return fr;
}
int main() {
struct Personal_Info p1 = {105, "123 Main St"};
struct Job_Info j1 = {105, "Software Engineer", 85000.00};
// 3. Perform the merge
struct Full_Record complete_record = merge_data(p1, j1);
// 4. Display the merged record
printf("--- Consolidated Employee Record ---\n");
printf("ID: %d\n", complete_record.id);
printf("Address: %s\n", complete_record.address);
printf("Title: %s\n", complete_record.title);
printf("Salary: $%.2f\n", complete_record.salary);
return 0;
}Code language: C++ (cpp)
Explanation:
This exercise demonstrates data consolidation.
The merge_data function receives copies of the two input structures. It creates a local Full_Record variable, copies the data from the two sources (using strcpy for strings and direct assignment for others), and then returns the newly populated Full_Record.
This is a clean way to combine related but separate pieces of data into a single, unified entity.
Exercise 20: Passing Array of Structures to a Function
Practice Problem: Define a Student structure (name, percentage). Input data for 4 students. Write a function calculate_class_average that accepts the array of structures and its size, calculates the average percentage of the entire class, and returns the result. Display the average in main
Given:
struct Student {
char name[50];
float percentage;
};Code language: C++ (cpp)
+ Hint
When passing the array, it decays to a pointer, so the function receives the address (pass-by-reference). Iterate through the array using a loop, sum the percentage members, and divide by the size.
+ Show Solution
#include <stdio.h>
struct Student {
char name[50];
float percentage;
};
// 1. Function to calculate average
float calculate_class_average(struct Student students[], int size) {
float total_percentage = 0.0;
for (int i = 0; i < size; i++) {
// Access members via index
total_percentage += students[i].percentage;
}
if (size > 0) {
return total_percentage / size;
}
return 0.0;
}
int main() {
const int CLASS_SIZE = 4;
struct Student class_data[CLASS_SIZE] = {
{"Leo", 88.0},
{"Mia", 91.5},
{"Noah", 79.0},
{"Pia", 95.5}
};
float average;
// 2. Call the function
average = calculate_class_average(class_data, CLASS_SIZE);
printf("Class Size: %d students\n", CLASS_SIZE);
printf("The Class Average Percentage is: %.2f%%\n", average);
return 0;
}Code language: C++ (cpp)
Explanation:
The function receives the array as a pointer to the first element (struct Student *students). It then iterates from i=0 to i=size−1, accessing the percentage of each student using the standard array index notation (students[i].percentage). It accumulates the sum and divides by the total number of students (size) to calculate and return the class average.
Exercise 21: Complex Number Structure (Addition)
Practice Problem: Define a structure ComplexNumber with members for the real and imaginary parts (both floats). Write a function add_complex that takes two ComplexNumber structures as input and returns a third ComplexNumber structure that is the sum of the two inputs. ((a+bi)+(c+di)=(a+c)+(b+d)i).
Given:
// 1. Structure Definition
struct ComplexNumber {
float real;
float imaginary;
};Code language: C++ (cpp)
Expected Output:
C1 = 3.50 + 2.00i
C2 = 1.20 + 4.30i
Sum = 4.70 + 6.30i
+ Hint
Sum the real parts together and the imaginary parts together. The function will have the signature: struct ComplexNumber add_complex(struct ComplexNumber n1, struct ComplexNumber n2).
+ Show Solution
#include <stdio.h>
// 1. Structure Definition
struct ComplexNumber {
float real;
float imaginary;
};
// 2. Function to add two complex numbers
struct ComplexNumber add_complex(struct ComplexNumber n1, struct ComplexNumber n2) {
struct ComplexNumber result;
result.real = n1.real + n2.real;
result.imaginary = n1.imaginary + n2.imaginary;
return result;
}
// Helper function to display complex number
void display_complex(struct ComplexNumber n) {
printf("%.2f + %.2fi", n.real, n.imaginary);
}
int main() {
struct ComplexNumber c1 = {3.5, 2.0};
struct ComplexNumber c2 = {1.2, 4.3};
// 3. Perform the addition
struct ComplexNumber sum = add_complex(c1, c2);
// 4. Display the result
printf("C1 = "); display_complex(c1); printf("\n");
printf("C2 = "); display_complex(c2); printf("\n");
printf("Sum = "); display_complex(sum); printf("\n");
return 0;
}Code language: C++ (cpp)
Explanation:
The add_complex function is designed to work with the ComplexNumber data type. It accepts two complex numbers (pass-by-value), creates a local result structure, calculates the new real and imaginary parts by simple addition, and returns the entire result structure.
This exemplifies how structures can be used to treat related data as a single unit when performing mathematical operations.
Exercise 22: Simple Inventory Management (Application)
Practice Problem: Define a structure for an Item (ID, name, quantity, unit_price). Implement two functions: add_item (to input data for a new item) and calculate_value (which takes an Item and returns its total inventory value: Quantity×Price). In main, use these functions for three items and display the total inventory value of all three.
Given:
struct Item {
int id;
char name[50];
int quantity;
float unit_price;
};Code language: C++ (cpp)
Expected Output:
Item ID 100
Enter Name: Notebook
Enter Quantity: 5
Enter Unit Price: $5
Item ID 101
Enter Name: Pen
Enter Quantity: 10
Enter Unit Price: $2
Item ID 102
Enter Name: Pencil
Enter Quantity: 10
Enter Unit Price: $1
--- Total Inventory Value ---
Total value of all items: $55.00
+ Hint
The add_item function should return the filled Item structure. The total inventory value is the sum of calculate_value called for each item.
+ Show Solution
#include <stdio.h>
struct Item {
int id;
char name[50];
int quantity;
float unit_price;
};
// 1. Function to create and return an Item structure
struct Item add_item(int item_id) {
struct Item i;
i.id = item_id;
printf("Item ID %d\n", i.id);
printf(" Enter Name: ");
scanf("%s", i.name);
printf(" Enter Quantity: ");
scanf("%d", &i.quantity);
printf(" Enter Unit Price: $");
scanf("%f", &i.unit_price);
return i;
}
// 2. Function to calculate item value
float calculate_value(struct Item i) {
return (float)i.quantity * i.unit_price;
}
int main() {
struct Item inventory[3];
float total_value = 0.0;
for (int i = 0; i < 3; i++) {
inventory[i] = add_item(100 + i);
total_value += calculate_value(inventory[i]);
}
printf("\n--- Total Inventory Value ---\n");
printf("Total value of all items: $%.2f\n", total_value);
return 0;
}Code language: C++ (cpp)
Explanation:
This exercise uses structures to model a real-world entity (Item). The add_item function encapsulates the input logic, returning a populated Item structure. The calculate_value function takes an item and performs a calculation specific to that item’s data. In main, we loop through an array of items, call these functions, and aggregate the results to maintain the total inventory value.

Leave a Reply