PYnative

Python Programming

  • Learn Python
    • Python Tutorials
    • Python Basics
    • Python Interview Q&As
  • Exercises
    • Python Exercises
    • C Programming Exercises
    • C++ Exercises
  • Quizzes
  • Code Editor
    • Online Python Code Editor
    • Online C Compiler
    • Online C++ Compiler
Home » C Programming Exercises » C Programming Structure and Union Exercises: 22 Coding Problems with Solutions

C Programming Structure and Union Exercises: 22 Coding Problems with Solutions

Updated on: January 7, 2026 | Leave a Comment

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)
Run

Explanation:

  • The program first defines the Student structure template. In main(), a variable s1 of 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 the s1 variable. 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)
Run

Explanation:

  • The structure variable b1 of type struct Book is 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” to b1.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)
Run

Explanation:

  • The declaration struct Student students[3]; creates an array where each element is an entire Student structure.
  • The first loop handles input, accessing each element using students[i].member. The second loop iterates through the array, comparing students[i].percentage with the percentage at students[max_index].
  • If a higher value is found, max_index is updated. Finally, the details of the student at the stored max_index are 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)
Run

Explanation:

  • The Employee structure is defined to include an entire instance of the Date structure, 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)
Run

Explanation:

  • The structure rect1 is passed to the function calculate_properties using pass-by-value. This means a complete copy of the structure’s data (length and width) is made and stored in the function’s local variable r.
  • 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 void return type. The original structure rect1 in main remains 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)
Run

Explanation:

  • The function get_rectangle_data is declared to return a value of type struct Rectangle. Inside the function, a local struct Rectangle variable r is populated.
  • The statement return r; copies the entire content of the local structure r back to the calling function (main). In main, the returned structure copy is stored in the variable r1, 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)
Run

Explanation:

  • car_ptr is a pointer designed to hold the memory address of a struct Car.
  • By assigning car_ptr = &my_car;, it points to the my_car variable.
  • The arrow operator (->) is syntactical shorthand for dereferencing the pointer and then accessing a member. For example, car_ptr->model_year is 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)
Run

Explanation:

  • C does not allow direct comparison of two structures using the equality operator (==) like if (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)
Run

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 n1 and n2. The line n1.next = &n2; establishes the link, allowing us to navigate from n1 to n2. The expression n1.next->data uses the pointer stored in n1.next to access the data member of the node it points to (which is n2).

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)
Run

Explanation:

  • The malloc() function reserves a block of memory equal to the size of struct Circle at runtime and returns a generic pointer (void *). This is cast to struct Circle * and stored in c_ptr.
  • Since c_ptr is 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:

  1. Assign a value to the integer member (i) and print it.
  2. Immediately assign a value to the float member (f) and print it.
  3. 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)
Run

Explanation:

  • The union Data reserves memory sufficient only for its largest member (which is str[20], likely 20 bytes).
  • When d.i = 10 is executed, 10 is stored in that shared memory. When d.f = 250.75 is executed next, the 4 bytes used for the float member overwrite the 4 bytes previously used for the integer.
  • Attempting to read d.i afterward 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)
Run

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)
Run

Explanation:

  • The structure Asset acts 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 info union is the same regardless of whether we store a license plate or a property ID. The if/else logic uses the structure’s type field 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)
Run

Explanation:

  • An enumeration in C defines a set of named integer constants. By setting MONDAY = 1, we initialize its underlying integer value. SUNDAY takes 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)
Run

Explanation:

  • The enum Color provides a clean, self-documenting way to represent colors using integer values. By making product_color an enum Color type, the code clearly restricts the acceptable values for the color field.
  • We assign the symbolic name GREEN (which is integer 1). The switch statement 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)
Run

Explanation:

  • The function pointer op_func makes the Operation structure flexible. We can dynamically change the behavior of the structure by simply assigning a different function address (add or subtract) 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)
Run

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)
Run

Explanation:

  • The search_employee function 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 id matches the search_id, the details are printed, the found flag is set to true, and the loop breaks. If the loop completes without finding a match, the !found condition 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)
Run

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)
Run

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)
Run

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)
Run

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.

Filed Under: C Programming Exercises

Did you find this page helpful? Let others know about it. Sharing helps me continue to create free Python resources.

TweetF  sharein  shareP  Pin

About Vishal

I’m Vishal Hule, the Founder of PYnative.com. As a Python developer, I enjoy assisting students, developers, and learners. Follow me on Twitter.

Related Tutorial Topics:

C Programming Exercises

All Coding Exercises:

C Exercises
C++ Exercises
Python Exercises

Python Exercises and Quizzes

Free coding exercises and quizzes cover Python basics, data structure, data analytics, and more.

  • 15+ Topic-specific Exercises and Quizzes
  • Each Exercise contains 25+ questions
  • Each Quiz contains 25 MCQ
Exercises
Quizzes

Leave a Reply Cancel reply

your email address will NOT be published. all comments are moderated according to our comment policy.

Use <pre> tag for posting code. E.g. <pre> Your entire code </pre>

In: C Programming Exercises
TweetF  sharein  shareP  Pin

  C Exercises

  • All C Exercises
  • C Exercise for Beginners
  • Intermediate C Exercises
  • C Variable and Data Type Exercise
  • C Loops Exercise
  • C Functions Exercise
  • C Arrays Exercise
  • C String Exercise
  • C Pointers Exercise
  • C File Handling Exercise
  • C Structures and Unions Exercise

All Coding Exercises

C Exercises C++ Exercises Python Exercises

About PYnative

PYnative.com is for Python lovers. Here, You can get Tutorials, Exercises, and Quizzes to practice and improve your Python skills.

Follow Us

To get New Python Tutorials, Exercises, and Quizzes

  • Twitter
  • Facebook
  • Sitemap

Explore Python

  • Learn Python
  • Python Basics
  • Python Databases
  • Python Exercises
  • Python Quizzes
  • Online Python Code Editor
  • Python Tricks

Coding Exercises

  • C Exercises
  • C++ Exercises
  • Python Exercises

Legal Stuff

  • About Us
  • Contact Us

We use cookies to improve your experience. While using PYnative, you agree to have read and accepted our:

  • Terms Of Use
  • Privacy Policy
  • Cookie Policy

Copyright © 2018–2026 pynative.com