Structures, Enumerations, and typedef are foundational C++ concepts essential for organizing complex data, managing memory, and improving code clarity.
This article contains 25 practical C++ exercises covering three foundational C++ concepts: Structures, Enumerations, and the typedef keyword.
Each exercise provides a clear Practice Problem, a helpful hint, a complete C++ solution, and a detailed explanation, ensuring you not only solve the problem but deeply understand why the solution works.
Also, See: C++ Exercises with 10 topic-wise sets and 300+ practice questions.
What You’ll Practice
- Structures: Defining, accessing members (dot operator), nesting structures, arrays of structures, and using pointers with structures.
- Enumerations: Working with C-style enums and the modern, type-safe scoped enums (
enum class) for defining constants. - Typedef: Creating aliases for basic, complex types, and function pointers to simplify declarations and enhance readability.
- Combined Modeling: Integrating all three concepts to model complex data effectively.
+ Table Of Contents
Table of contents
- Exercise 1: Define a Book Structure
- Exercise 2: Read and Display Book Data
- Exercise 3: Array of Structures (Books)
- Exercise 4: Function to Calculate Total Price
- Exercise 5: Nested Structure (Student Date of Birth)
- Exercise 6: Pointers to Structures
- Exercise 7: Dynamic Structure Allocation
- Exercise 8: Passing Structure to Function by Reference
- Exercise 9: Finding the Highest Price
- Exercise 10: Basic Enum (Days of the Week)
- Exercise 11: Enum in a switch Statement
- Exercise 12: Converting Integer to Enum
- Exercise 13: Scoped Enum ( enum class )
- Exercise 14: Scoped Enum as Function Parameter
- Exercise 15: Using Enums for Array Indexing
- Exercise 16: Mixing Enum and Struct
- Exercise 17: Bit Flags using Enum
- Exercise 18: Basic typedef
- Exercise 19: typedef for Function Pointers
- Exercise 20: typedef for a Structure
- Exercise 21: typedef for a Pointer to a Structure
- Exercise 22: Combined Exercise: Student Records (Struct & Typedef)
- Exercise 23: Combined Exercise of Inventory System (Struct, Enum Class, Typedef)
- Exercise 24: Combined Exercise: Movie Ratings
- Exercise 25: Type Safety with Scoped Enum and Struct
- Exercise 26: Advanced Combined Exercise (Employee Pay)
Exercise 1: Define a Book Structure
Practice Problem: Create a structure named Book to hold information about a library book. The structure must contain three members: a std::string for the book’s title, a std::string for the author’s name, and a float for the book’s price.
Expected Output:
Book Title: The Hitchhiker's Guide to the Galaxy
Price: $15.99
+ Hint
- Define the structure outside the
mainfunction. In thedisplay_pointfunction, use the dot operator (.) to access thexandymembers of the passed structure variable. - Remember to include the
<string>header for using thestd::stringdata type within your structure definition.
+ Show Solution
#include <string>
#include <iostream>
// Define the Book structure
struct Book {
std::string title;
std::string author;
float price;
};
int main() {
// Example of declaring a variable of type Book
Book b1;
b1.title = "The Hitchhiker's Guide to the Galaxy";
b1.author = "Douglas Adams";
b1.price = 15.99f; // 'f' suffix denotes a float literal
std::cout << "Book Title: " << b1.title << std::endl;
std::cout << "Price: $" << b1.price << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise shows how structures can combine different data types (
std::stringandfloat) into one logical unit. TheBookstructure is a custom data type that effectively models a real-world entity, making the code more readable and organized. - In C++, structure members are public by default. The
display_pointfunction demonstrates how to pass a structure by value to a function and access its individual members using the dot operator.
Exercise 2: Read and Display Book Data
Practice Problem: Using the Book structure defined in Exercise 2, write a complete C++ program that prompts the user to enter the title, author, and price for a single book. After reading the input, the program should display all the captured information back to the console.
Expected Output:
Enter Book Title: The Hitchhiker's Guide to the Galaxy
Enter Author Name: Douglas Adams, Eoin Colfer, Thomas Tidholm
Enter Price: $16
--- Book Information ---
Title: The Hitchhiker's Guide to the Galaxy
Author: Douglas Adams, Eoin Colfer, Thomas Tidholm
Price: $16.00
+ Hint
Use std::getline(std::cin, string_variable) to read strings that might contain spaces (like titles and author names). Use std::cin for the float price.
+ Show Solution
#include <iostream>
#include <string>
#include <limits> // Required for clearing the input buffer
struct Book {
std::string title;
std::string author;
float price;
};
int main() {
Book my_book;
// Read input from the user
std::cout << "Enter Book Title: ";
// Use getline to capture titles with spaces
std::getline(std::cin, my_book.title);
std::cout << "Enter Author Name: ";
std::getline(std::cin, my_book.author);
std::cout << "Enter Price: $";
std::cin >> my_book.price;
// Display the data
std::cout << "\n--- Book Information ---" << std::endl;
std::cout << "Title: " << my_book.title << std::endl;
std::cout << "Author: " << my_book.author << std::endl;
// Set precision for better currency display
std::cout.precision(2);
std::cout << std::fixed << "Price: $" << my_book.price << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise demonstrates practical input/output operations with a structure.
- Note the use of
std::getlinefor strings, which is essential when the input may contain spaces. The structure variablemy_bookholds all three pieces of data, which are accessed and modified using the dot operator
Exercise 3: Array of Structures (Books)
Practice Problem: Declare an array capable of storing information for 3 Book structures. Write a program to loop through the array, prompting the user to input the data (title, author, price) for each of the 3 books. Finally, loop through the array again to display the data for all 3 books.
Expected Output:
--- Enter data for Book 1 ---
Title: The C++ Programming Language
Author: Bjarne Stroustrup
Price: $10
--- Enter data for Book 2 ---
Title: Programming In C++
Author: Ashok N. Kamthane
Price: $9
--- Enter data for Book 3 ---
Title: C++ How To Program
Author: Paul Deitel & Harvey Deitel
Price: $11
===================================
ALL BOOKS INVENTORY
===================================
Book 1: The C++ Programming Language by Bjarne Stroustrup ($10)
Book 2: Programming In C++ by Ashok N. Kamthane ($9)
Book 3: C++ How To Program by Paul Deitel & Harvey Deitel ($11)
+ Hint
- Use a
forloop that iterates from 0 to 2. Inside the loop, you can access the members of the current book using array notation (e.g.,books[i].title). - You will need to handle the input buffer carefully if mixing
std::cinandstd::getlinein a loop by usingstd::cin.ignore().
+ Show Solution
#include <iostream>
#include <string>
#include <limits>
struct Book {
std::string title;
std::string author;
float price;
};
const int MAX_BOOKS = 3;
int main() {
Book books[MAX_BOOKS];
// Input loop
for (int i = 0; i < MAX_BOOKS; ++i) {
std::cout << "\n--- Enter data for Book " << i + 1 << " ---" << std::endl;
// Clear the input buffer if necessary from previous numeric input
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Title: ";
std::getline(std::cin, books[i].title);
std::cout << "Author: ";
std::getline(std::cin, books[i].author);
std::cout << "Price: $";
std::cin >> books[i].price;
}
// Output loop
std::cout << "\n===================================" << std::endl;
std::cout << " ALL BOOKS INVENTORY " << std::endl;
std::cout << "===================================" << std::endl;
for (int i = 0; i < MAX_BOOKS; ++i) {
std::cout << "Book " << i + 1 << ": " << books[i].title
<< " by " << books[i].author
<< " ($" << books[i].price << ")" << std::endl;
}
return 0;
}Code language: C++ (cpp)
Explanation:
- An array of structures is a common way to manage collections of records.
- The
books[MAX_BOOKS]declaration creates a contiguous block of memory to store 3Bookobjects. - The
forloops iterate over the array, using the indexito access each individual book structure. The members are accessed via the dot operator applied to the array element, e.g.,books[i].title.
Exercise 4: Function to Calculate Total Price
Practice Problem: Building upon the array of Book structures, write a function named calculate_total_price. This function should accept the array of Book structures and the number of books as arguments. It must return a float representing the sum of the prices of all books in the array.
Expected Output:
Total price of all 3 books: $35.49
+ Hint
- The function signature will be
float calculate_total_price(const Book books[], int count). - Use a loop inside the function to accumulate the total price, accessing the
pricemember of each element. Useconstto ensure the function does not accidentally modify the array.
+ Show Solution
#include <iostream>
#include <string>
struct Book {
std::string title;
std::string author;
float price;
};
// Function to calculate the total price
float calculate_total_price(const Book books[], int count) {
float total = 0.0f;
for (int i = 0; i < count; ++i) {
total += books[i].price; // Accumulate the price of each book
}
return total;
}
int main() {
const int count = 3;
Book library[count] = {
{"Dune", "Frank Herbert", 12.50f},
{"1984", "George Orwell", 8.99f},
{"The Hobbit", "J.R.R. Tolkien", 14.00f}
};
float grand_total = calculate_total_price(library, count);
std::cout << "Total price of all " << count << " books: $";
std::cout.precision(2);
std::cout << std::fixed << grand_total << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- The function
calculate_total_pricetakes the array (which decays to a pointer) and its size. - The
constkeyword is a good practice as the function only reads the data. It iterates through the books, sums theirpricemembers, and returns the final sum. This shows how structures can be easily manipulated within functions for common data processing tasks.
Exercise 5: Nested Structure (Student Date of Birth)
Practice Problem: Define a structure DateOfBirth with three integer members: day, month, and year. Next, define a structure Student that contains the student’s std::string name and a member of the type DateOfBirth. Create an instance of the Student structure and initialize its nested members, then display all the student’s information.
Expected Output:
Student Name: Ella Fitzgerald
Date of Birth: 4/25/2008
+ Hint
- The
DateOfBirthstructure must be defined before theStudentstructure. - To access the innermost members (like
day), you will chain the dot operator:student_variable.dob.day.
+ Show Solution
#include <iostream>
#include <string>
// 1. Define the inner structure
struct DateOfBirth {
int day;
int month;
int year;
};
// 2. Define the outer structure, containing an instance of the inner structure
struct Student {
std::string name;
DateOfBirth dob; // Nested structure member
};
int main() {
// Create an instance and initialize members
Student s1;
s1.name = "Ella Fitzgerald";
// Initialize the nested structure members
s1.dob.day = 25;
s1.dob.month = 4;
s1.dob.year = 2008;
// Display the data
std::cout << "Student Name: " << s1.name << std::endl;
std::cout << "Date of Birth: " << s1.dob.month << "/" << s1.dob.day << "/" << s1.dob.year << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- Nested structures are used to logically group related data.
- Here, the date of birth is a distinct concept within the student’s data.
- Accessing the deepest member (e.g.,
day) requires using the dot operator multiple times to traverse the hierarchy: from theStudentvariable (s1) to theDateOfBirthmember (dob) and finally to thedaymember.
Exercise 6: Pointers to Structures
Practice Problem: Define a structure Rectangle with two float members: length and width. Declare a pointer to a Rectangle structure, dynamically allocate memory for it, and then use the pointer to read and display the rectangle’s dimensions.
Given:
struct Rectangle {
float length;
float width;
};Code language: C++ (cpp)
Expected Output:
Enter rectangle length: 10
Enter rectangle width: 20
Rectangle Dimensions:
Length: 10
Width: 20
Area: 200
+ Hint
- Use the
newoperator for dynamic allocation. - Use the arrow operator (
->) to access the structure members via the pointer. - Remember to use
deleteto free the allocated memory.
+ Show Solution
#include <iostream>
struct Rectangle {
float length;
float width;
};
int main() {
// Declare a pointer to a Rectangle structure
Rectangle* rect_ptr;
// Dynamically allocate memory for a Rectangle
rect_ptr = new Rectangle;
// Use the arrow operator (->) to access and set members
std::cout << "Enter rectangle length: ";
std::cin >> rect_ptr->length;
std::cout << "Enter rectangle width: ";
std::cin >> rect_ptr->width;
// Use the arrow operator to access and display members
std::cout << "\nRectangle Dimensions:" << std::endl;
std::cout << "Length: " << rect_ptr->length << std::endl;
std::cout << "Width: " << rect_ptr->width << std::endl;
// Calculate and display area
float area = rect_ptr->length * rect_ptr->width;
std::cout << "Area: " << area << std::endl;
// Free the dynamically allocated memory
delete rect_ptr;
rect_ptr = nullptr; // Good practice to set pointer to null
return 0;
}Code language: C++ (cpp)
Explanation:
- Pointers to structures are essential for dynamic memory management and for passing large structures to functions efficiently (by address).
- The arrow operator (
->) is a convenient shortcut for dereferencing the pointer and accessing a member simultaneously. For example,rect_ptr->lengthis equivalent to(*rect_ptr).length.
Exercise 7: Dynamic Structure Allocation
Practice Problem: Use the Book structure from Exercise 2. Write a program to dynamically create a single Book structure using the new keyword. Prompt the user to enter the book’s details (title, author, price) and store them in the dynamically allocated structure. Finally, display the data and explicitly release the memory using the delete keyword.
Given:
struct Book {
std::string title;
std::string author;
float price;
};Code language: C++ (cpp)
Expected Output:
--- Enter New Book Details ---
Title: book1
Author: author1
Price: $10
--- Confirmation ---
Title: book1
Author: author1
Price: $10
+ Hint
- The process is similar to Exercise 6, but emphasizes the
newanddeleteoperations to manage memory on the heap. - Access members using the arrow operator (
->). - Make sure to include the
<limits>header for buffer clearing.
+ Show Solution
#include <iostream>
#include <string>
#include <limits> // <-- ADD THIS LINE to fix the error
struct Book {
std::string title;
std::string author;
float price;
};
int main() {
// Dynamic allocation of a single Book structure
Book* new_book = new Book;
// Clear buffer just in case of leftover newline from previous input
// The error was fixed by including <limits>
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "--- Enter New Book Details ---" << std::endl;
// Input using the pointer
std::cout << "Title: ";
std::getline(std::cin, new_book->title);
std::cout << "Author: ";
std::getline(std::cin, new_book->author);
std::cout << "Price: $";
std::cin >> new_book->price;
// Display the data using the pointer
std::cout << "\n--- Confirmation ---" << std::endl;
std::cout << "Title: " << new_book->title << std::endl;
std::cout << "Author: " << new_book->author << std::endl;
std::cout << "Price: $" << new_book->price << std::endl;
// Crucial step: Free the memory allocated on the heap
delete new_book;
new_book = nullptr;
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise highlights the difference between stack and heap memory.
- Using
new Bookallocates memory on the heap and returns a pointer to that location. - This memory persists until explicitly released with
delete. This is common practice when the memory needed is unknown at compile time.
Exercise 8: Passing Structure to Function by Reference
Practice Problem: Create a C++ structure named Point. This structure should have two integer members: x and y, representing coordinates in a two-dimensional plane. Write a function named double_coordinates that takes a Point structure by reference. Inside this function, multiply both the x and y coordinates by 2. Demonstrate that the original Point variable in main has been modified after the function call.
Given:
struct Point {
int x;
int y;
};Code language: C++ (cpp)
Expected Output:
Original Point: (5, 10)
Point After Doubling: (10, 20)
+ Hint
- The function signature should include an ampersand (
&) to denote a reference parameter:void double_coordinates(Point &p). - When passing by reference, changes made inside the function directly affect the original variable.
+ Show Solution
#include <iostream>
struct Point {
int x;
int y;
};
// Function that takes a structure by reference
void double_coordinates(Point &p) {
p.x *= 2; // Directly modifies the original p1 in main
p.y *= 2; // Directly modifies the original p1 in main
}
int main() {
Point p1 = {5, 10};
std::cout << "Original Point: (" << p1.x << ", " << p1.y << ")" << std::endl;
// Call the function, passing by reference
double_coordinates(p1);
std::cout << "Point After Doubling: (" << p1.x << ", " << p1.y << ")" << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- Passing a structure by reference (using
Point &p) allows a function to modify the original variable passed from the calling function (mainin this case). - This is more efficient than passing by value (which creates a copy) when dealing with large structures, and it is the necessary method when the function’s purpose is to modify the structure’s data.
Exercise 9: Finding the Highest Price
Practice Problem: Using an array of Book structures (like in Exercise 4), write a function named find_most_expensive that accepts the vector of books. The function should iterate through the books and return the title (a std::string) of the book with the highest price.
Given:
Code language: C++ (cpp)
Expected Output:
The most expensive book is: Design Patterns
+ Hint
You will need a loop and two tracking variables: one to store the current maximum price found so far, and another to store the index or the title of the book corresponding to that maximum price.
+ Show Solution
#include <iostream>
#include <string>
#include <vector>
struct Book {
std::string title;
std::string author;
float price;
};
// Function to find the title of the most expensive book
std::string find_most_expensive(const std::vector<Book>& books) {
if (books.empty()) {
return "No books available";
}
// Start with the first book as the most expensive
float max_price = books[0].price;
std::string max_title = books[0].title;
// Iterate starting from the second book
for (size_t i = 1; i < books.size(); ++i) {
if (books[i].price > max_price) {
max_price = books[i].price; // Update max price
max_title = books[i].title; // Update the title
}
}
return max_title;
}
int main() {
// Initialize a vector of books
std::vector<Book> library = {
{"The C++ Programming Language", "Bjarne Stroustrup", 45.99f},
{"Effective C++", "Scott Meyers", 35.50f},
{"Design Patterns", "Erich Gamma et al.", 50.00f}
};
std::string best_seller = find_most_expensive(library);
std::cout << "The most expensive book is: " << best_seller << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- The function initializes the maximum price and corresponding title with the data from the first element.
- It then loops through the rest of the elements, performing a comparison on the
pricemember. If a higher price is found, both themax_priceand themax_titleare updated. This demonstrates accessing specific members of structured data within a comparison loop.
Exercise 10: Basic Enum (Days of the Week)
Practice Problem: Define an enumeration named Day for the days of the week, starting with Sunday and ending with Saturday. Write a program to declare a variable of type Day, assign it the value Wednesday, and then print the underlying integer value of that day to the console.
Expected Output:
The integer value of Wednesday is: 3
+ Hint
- By default, the first enumerator (
Sunday) is assigned 0, and each subsequent enumerator increments by 1. - You do not need to explicitly assign values unless you want to change this default behavior. When printing the enum value, you may need to cast it to an
int.
+ Show Solution
#include <iostream>
// Define the Day enumeration
enum Day {
Sunday, // 0
Monday, // 1
Tuesday, // 2
Wednesday, // 3
Thursday, // 4
Friday, // 5
Saturday // 6
};
int main() {
// Declare a variable and assign a value
Day today = Wednesday;
std::cout << "The integer value of Wednesday is: ";
// Cast the enum variable to an int to print its underlying value
std::cout << static_cast<int>(today) << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- C-style enumerations (
enum) provide a set of named integer constants. - By default, the constants are assigned values sequentially starting from 0.
- The program demonstrates declaration, assignment, and the use of
static_cast<int>to explicitly retrieve and print the integer value associated with the enumeratorWednesday(which is 3).
Exercise 11: Enum in a switch Statement
Practice Problem: Define an enumeration TrafficLight with three states: Red, Yellow, and Green. Write a function named get_action that accepts a TrafficLight value and uses a switch statement to print the appropriate driver action: “Stop,” “Prepare to stop,” or “Go.” Demonstrate the function call in main.
Expected Output:
Light is 2. Action: Go
Light is 1. Action: Prepare to stop
+ Hint
The switch statement is the ideal control structure for handling different enum states. You can use the enumerator names (e.g., Red) directly in the case labels.
+ Show Solution
#include <iostream>
#include <string>
// Define the TrafficLight enumeration
enum TrafficLight {
Red,
Yellow,
Green
};
// Function to determine action based on light state
void get_action(TrafficLight light) {
std::cout << "Light is " << light << ". Action: ";
switch (light) {
case Red:
std::cout << "Stop" << std::endl;
break;
case Yellow:
std::cout << "Prepare to stop" << std::endl;
break;
case Green:
std::cout << "Go" << std::endl;
break;
}
}
int main() {
TrafficLight current_light = Green;
get_action(current_light);
current_light = Yellow;
get_action(current_light);
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise shows how enumerations improve code readability by replacing “magic numbers” (like 0, 1, 2) with meaningful names.
- The
switchstatement uses the enumerator names for clear and robust branching logic, making it easy to see which action corresponds to which traffic light state.
Exercise 12: Converting Integer to Enum
Practice Problem: Use the TrafficLight enumeration from Exercise 11. Write a program that prompts the user to input a number (0 for Red, 1 for Yellow, 2 for Green). Convert this integer input into a TrafficLight enum type. Use a function to display the resulting light status. Include basic input validation to check if the number is within the valid range (0 to 2).
Given:
enum TrafficLight {
Red,
Yellow,
Green
};Code language: C++ (cpp)
Expected Output:
Enter light code (0=Red, 1=Yellow, 2=Green): 2
Status: Green - Go
+ Hint
You can convert an integer to an enum value using a simple static cast: TrafficLight light = static_cast<TrafficLight>(input_int);.
+ Show Solution
#include <iostream>
enum TrafficLight {
Red,
Yellow,
Green
};
void display_light_status(TrafficLight light) {
switch (light) {
case Red: std::cout << "Status: Red - Stop" << std::endl; break;
case Yellow: std::cout << "Status: Yellow - Caution" << std::endl; break;
case Green: std::cout << "Status: Green - Go" << std::endl; break;
}
}
int main() {
int input_val;
std::cout << "Enter light code (0=Red, 1=Yellow, 2=Green): ";
std::cin >> input_val;
if (input_val >= Red && input_val <= Green) {
// Safe conversion using static_cast
TrafficLight user_light = static_cast<TrafficLight>(input_val);
display_light_status(user_light);
} else {
std::cout << "Error: Invalid light code entered." << std::endl;
}
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise demonstrates the mechanism for converting raw user input into a type-safe enumeration. The cast
static_cast<TrafficLight>(input_val)tells the compiler to treat the integer as aTrafficLightvalue. - The input validation step is important because without it, an invalid input (like 99) would still be converted, leading to undefined behavior or logical errors within the
switchstatement.
Exercise 13: Scoped Enum (enum class)
Practice Problem: Redefine the TrafficLight enumeration from Exercise 11 as a scoped enum (enum class). Attempt to access and use the enumerators (Red, Yellow) without using the scope resolution operator (::). Then, correct the code by using the scope resolution operator (TrafficLight::Red) and demonstrate successful compilation and assignment.
Note: Scoped enums, introduced in C++11.
Given:
// Define the Scoped Enum
enum class TrafficLight {
Red,
Yellow,
Green
};Code language: C++ (cpp)
Expected Output:
Current light is Green.
Underlying value:
+ Hint
- Scoped enums, prevent namespace pollution. You must use the enum class name followed by
::to access its members. - You will also need a
static_castif you want to explicitly print the integer value of a scoped enum member.
+ Show Solution
#include <iostream>
// Define the Scoped Enum
enum class TrafficLight {
Red,
Yellow,
Green
};
int main() {
// Attempt 1: Accessing without scope (will fail compilation)
// TrafficLight light1 = Red; // ERROR: 'Red' is not declared in this scope
// Correct Access: Using the scope operator (::)
TrafficLight light2 = TrafficLight::Green;
std::cout << "Current light is Green." << std::endl;
// Accessing integer value requires explicit cast
std::cout << "Underlying value: " << static_cast<int>(light2) << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- Scoped enumerations (
enum class) are strongly typed and ensure that the enumerator names (likeRed) are only visible within the scope of the enum class itself (TrafficLight). - This prevents naming conflicts in large projects (namespace pollution). It also prevents implicit conversion to
int, forcing the use ofstatic_castfor type safety.
Exercise 14: Scoped Enum as Function Parameter
Practice Problem: Define a simple function named check_status that takes a parameter of the enum class TrafficLight type (from Exercise 13). Inside main, attempt to call this function by passing an ordinary integer (e.g., 0) instead of an enum value. Observe and describe the compiler error. Then, correct the function call by passing a valid, scoped enumerator.
Given:
enum class TrafficLight {
Red,
Yellow,
Green
};Code language: C++ (cpp)
Expected Output:
The status is not Red.
The status is Red.
+ Hint
Since scoped enums are strongly typed, the compiler will not allow the implicit conversion from int to TrafficLight. You must either pass a correctly scoped enumerator or use a static_cast to force the conversion.
+ Show Solution
#include <iostream>
enum class TrafficLight {
Red,
Yellow,
Green
};
void check_status(TrafficLight light) {
if (light == TrafficLight::Red) {
std::cout << "The status is Red." << std::endl;
} else {
std::cout << "The status is not Red." << std::endl;
}
}
int main() {
// 1. Attempt to pass an integer (Will cause a compiler error)
// check_status(1); // ERROR: Cannot convert 'int' to 'TrafficLight'
// 2. Correct call: Passing a valid enumerator
check_status(TrafficLight::Yellow);
// 3. Alternative correct call using static_cast
check_status(static_cast<TrafficLight>(0));
return 0;
}Code language: C++ (cpp)
Explanation:
- The compiler error, often “cannot convert ‘int’ to ‘TrafficLight’,” confirms the type safety of
enum class. - Unlike C-style enums, scoped enums prevent accidental use of integers where a specific enum type is expected. This strong typing helps catch bugs early and ensures that only valid, named states are used.
Exercise 15: Using Enums for Array Indexing
Practice Problem: Define an enumeration Month starting at JAN (0) through DEC (11). Declare an array of int named monthly_revenue with 12 elements. Use the Month enumerators to set and retrieve the revenue values for JAN, FEB, and MAR (e.g., set JAN to 5000 and print it).
Given:
/ Define the Month enumeration (implicitly 0 to 11)
enum Month {
JAN, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC
};Code language: C++ (cpp)
Expected Output:
January Revenue: $5000
March Revenue: $7800
Revenue for month 1 is $5000
Revenue for month 2 is $6200
Revenue for month 3 is $7800
+ Hint
Since C-style enums implicitly convert to int, you can use the enumerator directly as the index for the array, as the underlying integer value will correctly map to the array index.
+ Show Solution
#include <iostream>
#include <array>
// Define the Month enumeration (implicitly 0 to 11)
enum Month {
JAN, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC
};
int main() {
// Array to hold 12 months of revenue
std::array<int, 12> monthly_revenue = {0}; // Initialize all to 0
// Use enum values to index the array
monthly_revenue[JAN] = 5000;
monthly_revenue[FEB] = 6200;
monthly_revenue[MAR] = 7800;
std::cout << "January Revenue: $" << monthly_revenue[JAN] << std::endl;
std::cout << "March Revenue: $" << monthly_revenue[MAR] << std::endl;
// Demonstrate a loop using the enum
for (int m = JAN; m <= MAR; ++m) {
std::cout << "Revenue for month " << m + 1 << " is $" << monthly_revenue[m] << std::endl;
}
return 0;
}Code language: C++ (cpp)
Explanation:
- Using enumerators for array indexing significantly improves code clarity.
- Instead of writing
monthly_revenue[0], you writemonthly_revenue[JAN], which clearly indicates what that index represents. This is possible because the C-style enum values seamlessly convert to their underlying integer indices.
Exercise 16: Mixing Enum and Struct
Practice Problem: Define an enum class Status with values Pending, Shipped, and Delivered. Define a structure Order with an int for id, a float for amount, and a member of the type Status named current_status. Create and initialize an Order structure, setting its status to Shipped, and then print all its details.
Expected Output:
Order ID: 1001
Amount: $250.75
Status: Shipped
+ Hint
The enum definition can be outside the struct. Initialize the Status member using the scope resolution operator, e.g., my_order.current_status = Status::Shipped;.
+ Show Solution
#include <iostream>
#include <string>
// Define the Status enum class
enum class Status {
Pending,
Shipped,
Delivered
};
// Define the Order structure
struct Order {
int id;
float amount;
Status current_status; // Member is of enum class type
};
void display_status(Status s) {
switch (s) {
case Status::Pending: std::cout << "Pending"; break;
case Status::Shipped: std::cout << "Shipped"; break;
case Status::Delivered: std::cout << "Delivered"; break;
}
}
int main() {
Order my_order = {
1001,
250.75f,
Status::Shipped // Initialize the enum member
};
std::cout << "Order ID: " << my_order.id << std::endl;
std::cout << "Amount: $" << my_order.amount << std::endl;
std::cout << "Status: ";
display_status(my_order.current_status); // Pass enum to helper function
std::cout << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- This is a practical example of how structures and enumerations are used together to create a complex, meaningful data type.
- The
Orderstructure encapsulates various attributes, and theStatusenum ensures that the order’s state can only be one of the pre-defined valid options (Pending,Shipped, orDelivered), preventing invalid data assignment.
Exercise 17: Bit Flags using Enum
Practice Problem: Define a C-style enumeration Permissions where the values are powers of 2: READ (1), WRITE (2), and EXECUTE (4). Declare an integer variable user_permission. Use the bitwise OR (|) operator to assign the variable both READ and WRITE permissions. Then, use the bitwise AND (&) operator to check and print whether the WRITE permission is set for the user.
Expected Output:
User permission value: 3
CHECK: WRITE permission IS SET.
CHECK: EXECUTE permission is NOT set.
+ Hint
C-style enums are necessary for bit flags because they implicitly convert to integers, allowing bitwise operations. The check for a specific flag uses the expression: (variable & FLAG_NAME)
+ Show Solution
#include <iostream>
// Define C-style enum with powers of 2 for bit flags
enum Permissions {
NONE = 0,
READ = 1, // 001
WRITE = 2, // 010
EXECUTE = 4 // 100
};
int main() {
// Combine READ and WRITE permissions using bitwise OR (|)
int user_permission = READ | WRITE; // Result is 3 (011 binary)
std::cout << "User permission value: " << user_permission << std::endl;
// Check if WRITE permission is set using bitwise AND (&)
if (user_permission & WRITE) {
std::cout << "CHECK: WRITE permission IS SET." << std::endl;
} else {
std::cout << "CHECK: WRITE permission is NOT set." << std::endl;
}
// Check if EXECUTE permission is set
if (user_permission & EXECUTE) {
std::cout << "CHECK: EXECUTE permission IS SET." << std::endl;
} else {
std::cout << "CHECK: EXECUTE permission is NOT set." << std::endl;
}
return 0;
}Code language: C++ (cpp)
Explanation:
- Bit flags are an efficient way to store multiple boolean states in a single integer variable.
- By assigning each permission a unique power-of-2 value, they occupy distinct bit positions.
- Bitwise OR (
|) turns on multiple bits, and Bitwise AND (&) is used to check if a specific bit (flag) is set, returning true only if the corresponding bit is 1 in both the variable and the flag.
Exercise 18: Basic typedef
Practice Problem: Use the typedef keyword to create two new type aliases: Integer for the standard int data type and Text for the std::string data type. In the main function, declare variables using these new aliases and demonstrate that they behave identically to the original types by performing a simple arithmetic operation and string concatenation.
typedef is a powerful tool for improving code readability, especially when dealing with long or complex type names.
Expected Output:
Integer result (5 * 2): 10
Text message: Hello, World!
+ Hint
The syntax for typedef is: typedef existing_type new_name;. This simply provides an alternative name for a type that already exists.
+ Show Solution
#include <iostream>
#include <string>
// Use typedef to create type aliases
typedef int Integer;
typedef std::string Text;
int main() {
// Declare variables using the new aliases
Integer count = 5;
Text greeting = "Hello, ";
Text name = "World!";
// Demonstrate Integer
Integer result = count * 2;
std::cout << "Integer result (5 * 2): " << result << std::endl;
// Demonstrate Text
Text full_message = greeting + name;
std::cout << "Text message: " << full_message << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- By using
IntegerandText, the intent of the variables becomes clearer. - While modern C++ often prefers
usingaliases (e.g.,using Integer = int;),typedefremains fully valid, particularly for compatibility with C codebases.
Exercise 19: typedef for Function Pointers
Practice Problem: Use typedef to define a type alias named MathFunc for a function pointer that takes two int arguments and returns an int. Write two simple functions, add and subtract, matching this signature. Declare a variable of type MathFunc, assign it to the add function, and call it. Then, reassign it to the subtract function and call it again.
Expected Output:
Addition (10 + 5): 15
Subtraction (10 - 5): 5
+ Hint
- Defining a function pointer type can be syntactically complex, which is why
typedefis ideal: typedef int (*MathFunc)(int, int);. The asterisk (*) is placed around the alias name being defined.
+ Show Solution
#include <iostream>
// Typedef for a function pointer: returns int, takes (int, int)
typedef int (*MathFunc)(int, int);
// Functions that match the signature
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int main() {
// Declare a variable of the function pointer type
MathFunc operation_ptr;
// Assign to the add function
operation_ptr = add;
int result1 = operation_ptr(10, 5);
std::cout << "Addition (10 + 5): " << result1 << std::endl;
// Reassign to the subtract function
operation_ptr = subtract;
int result2 = operation_ptr(10, 5);
std::cout << "Subtraction (10 - 5): " << result2 << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- Function pointers are essential for implementing callbacks or command patterns, but their syntax can be cumbersome.
- The
typedefkeyword simplifies the declaration of the function pointer variableoperation_ptrfrom a complex line to a clear, single type name (MathFunc). - This vastly improves the readability of code that uses functions as arguments or variables.
Exercise 20: typedef for a Structure
Practice Problem: Define a structure named ComplexNumber with two float members: real and imaginary. Use typedef to create an alias CNum for this structure. Demonstrate how CNum simplifies declaration by creating a variable named z1 using the alias and a variable named z2 using the old struct ComplexNumber keyword, and verify they are the same type of object.
Expected Output:
Complex Number z1: 3 + 4i
Complex Number z2: 1.5 + -2.5i
+ Hint
- In C++, you can usually omit the
structkeyword when declaring a variable (e.g.,ComplexNumber z;). - However, using
typedefmakes the C++ syntax identical to any built-in type:CNum z1;. Thetypedefcan be combined with the structure definition.
+ Show Solution
#include <iostream>
// Define the structure and create the alias simultaneously
typedef struct ComplexNumber {
float real;
float imaginary;
} CNum; // CNum is the alias
int main() {
// Declaration using the alias (more concise)
CNum z1 = {3.0f, 4.0f};
// Declaration using the original struct name (no 'struct' keyword needed in C++)
ComplexNumber z2 = {1.5f, -2.5f};
std::cout << "Complex Number z1: " << z1.real << " + " << z1.imaginary << "i" << std::endl;
std::cout << "Complex Number z2: " << z2.real << " + " << z2.imaginary << "i" << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- In standard C, the
structkeyword is always required when declaring a structure variable (e.g.,struct ComplexNumber z;). typedefwas traditionally used in C to create a new type name that did not require thestructkeyword. While C++ relaxes this rule,typedef(or modernusingalias) is still helpful for creating short, convenient names likeCNum.
Exercise 21: typedef for a Pointer to a Structure
Practice Problem: Use the Book structure (from Exercise 2: title, author, price). Use typedef to create an alias PBook for a pointer to the Book structure. Declare a variable of type PBook, allocate memory for it using new, and use the pointer alias to set the book’s title to “The Odyssey”. Finally, display the title and release the memory.
Given:
struct Book {
std::string title;
std::string author;
float price;
};Code language: C++ (cpp)
Expected Output:
Title via PBook alias: The Odyssey
Author: Homer
+ Hint
- The pointer
typedefsyntax istypedef struct Book *PBook;. - When declaring variables, this allows
PBook my_ptr;instead ofstruct Book *my_ptr;. Access members using the arrow operator (->).
+ Show Solution
#include <iostream>
#include <string>
struct Book {
std::string title;
std::string author;
float price;
};
// Typedef for a pointer to the Book structure
typedef Book* PBook;
int main() {
// Declare a pointer using the alias PBook
PBook my_book_ptr = new Book;
// Assign data using the pointer (arrow operator)
my_book_ptr->title = "The Odyssey";
my_book_ptr->author = "Homer";
my_book_ptr->price = 10.99f;
// Display data
std::cout << "Title via PBook alias: " << my_book_ptr->title << std::endl;
std::cout << "Author: " << my_book_ptr->author << std::endl;
// Cleanup
delete my_book_ptr;
my_book_ptr = nullptr;
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise demonstrates the utility of
typedefin simplifying pointer declarations, which can often look confusing when combined with structures. PBookclearly signals that the variable is a pointer intended to hold aBookobject’s address, making pointer use less error-prone and easier to read.
Exercise 22: Combined Exercise: Student Records (Struct & Typedef)
Practice Problem: Define a structure StudentInfo with an int for ID and a float for GPA. Use typedef to alias the structure as Record. Declare an array of three Record objects and initialize them with sample data (ID and GPA). Write a function that accepts the array and prints the record of the student with the highest GPA.
Expected Output:
--- Top Student Record ---
ID: 102
GPA: 3.92
+ Hint
- Use initializer lists to quickly populate the array of structures.
- The logic to find the highest GPA, requiring a loop to track the maximum value and its index.
+ Show Solution
#include <iostream>
#include <string>
// Define struct and typedef alias
typedef struct StudentInfo {
int ID;
float GPA;
} Record;
void print_top_gpa(const Record records[], int count) {
if (count == 0) return;
float max_gpa = 0.0f;
int top_index = 0;
for (int i = 0; i < count; ++i) {
if (records[i].GPA > max_gpa) {
max_gpa = records[i].GPA;
top_index = i;
}
}
std::cout << "\n--- Top Student Record ---" << std::endl;
std::cout << "ID: " << records[top_index].ID << std::endl;
std::cout << "GPA: " << records[top_index].GPA << std::endl;
}
int main() {
const int num_students = 3;
// Declare and initialize an array of the aliased type 'Record'
Record class_roster[num_students] = {
{101, 3.85f},
{102, 3.92f},
{103, 3.70f}
};
print_top_gpa(class_roster, num_students);
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise combines the definition of a structured record with a
typedeffor convenience. - The
Recordalias makes the array declarationRecord class_roster[num_students]cleaner. - The function demonstrates standard structure processing: passing the array as a
constpointer and iterating through it to find an extreme value.
Exercise 23: Combined Exercise of Inventory System (Struct, Enum Class, Typedef)
Practice Problem: Define an enum class ItemType (Tool, Supply, Component). Define a structure InventoryItem with a std::string name, float price, and an ItemType member. Use typedef to alias InventoryItem as Item. Write a function print_items_by_type that accepts a list of Item objects and an ItemType, and prints only the items matching that type.
Expected Output:
--- Listing Items by Type ---
Name: Wrench, Price: $15
Name: Hammer, Price: $12
+ Hint
Use a std::vector<Item> to represent the list of items. In the filter function, iterate through the vector and use an if statement to compare the Item‘s internal ItemType member with the target type passed as an argument.
+ Show Solution
#include <iostream>
#include <string>
#include <vector>
// 1. Define Enum Class
enum class ItemType {
Tool,
Supply,
Component
};
// 2. Define Structure and Typedef Alias
typedef struct InventoryItem {
std::string name;
float price;
ItemType type;
} Item; // Item is the alias
// Function to print only items of a specific type
void print_items_by_type(const std::vector<Item>& inventory, ItemType target_type) {
std::cout << "\n--- Listing Items by Type ---" << std::endl;
for (const auto& item : inventory) {
if (item.type == target_type) {
std::cout << "Name: " << item.name << ", Price: $" << item.price << std::endl;
}
}
}
int main() {
std::vector<Item> warehouse = {
{"Wrench", 15.00f, ItemType::Tool},
{"Screws", 2.50f, ItemType::Supply},
{"Gearbox", 55.99f, ItemType::Component},
{"Hammer", 12.00f, ItemType::Tool}
};
// Call function to filter and print
print_items_by_type(warehouse, ItemType::Tool);
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise fully integrates all three concepts.
Item(viatypedef) makes the container type readable. - The
InventoryItemstructure usesItemType(viaenum class) to strictly categorize the items. The filter function’s core logic relies on the safe and explicit comparison of the scoped enum values.
Exercise 24: Combined Exercise: Movie Ratings
Practice Problem: Define an enum class Rating (G, PG, PG13, R, NC17). Define a structure Movie with a std::string title, int release year, and a Rating member. Use typedef to simplify the declaration of the Movie type to Film. Write a function check_age_restriction that accepts a Film and prints a message based on the rating (e.g., for ‘R’, print “Requires adult accompaniment for viewers under 17”)
Expected Output:
The Martian (2015): Parents Strongly Cautioned.
Pulp Fiction (1994): Restricted - Requires adult accompaniment.
+ Hint
The rating function is best implemented using a switch statement that covers all enumerator cases.
+ Show Solution
#include <iostream>
#include <string>
// 1. Define Enum Class
enum class Rating {
G,
PG,
PG13,
R,
NC17
};
// 2. Define Structure and Typedef Alias
typedef struct Movie {
std::string title;
int year;
Rating age_rating;
} Film; // Film is the alias
void check_age_restriction(const Film& f) {
std::cout << f.title << " (" << f.year << "): ";
switch (f.age_rating) {
case Rating::G:
std::cout << "General Audiences - All ages admitted." << std::endl;
break;
case Rating::PG:
std::cout << "Parental Guidance Suggested." << std::endl;
break;
case Rating::PG13:
std::cout << "Parents Strongly Cautioned." << std::endl;
break;
case Rating::R:
std::cout << "Restricted - Requires adult accompaniment." << std::endl;
break;
case Rating::NC17:
std::cout << "No one 17 and under admitted." << std::endl;
break;
}
}
int main() {
Film my_movie = {"The Martian", 2015, Rating::PG13};
Film rated_r = {"Pulp Fiction", 1994, Rating::R};
check_age_restriction(my_movie);
check_age_restriction(rated_r);
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise provides a realistic scenario where
typedefmakes the main logic easier to follow (Filminstead ofstruct Movie) and theRatingenum strictly enforces valid rating options. - The function
check_age_restrictiondemonstrates how to use the enum member within the structure to drive complex business logic (age restriction rules).
Exercise 25: Type Safety with Scoped Enum and Struct
Practice Problem: Define a structure ColorRGB with three unsigned char members: r, g, and b. Define a scoped enum PresetColor (Red, Green, Blue). Write a function getColor(PresetColor color) that takes a preset color and returns the corresponding ColorRGB structure (e.g., Red should return {255, 0, 0}). Demonstrate calling the function and printing the returned RGB values.
Given:
// 1. Structure for color data
struct ColorRGB {
unsigned char r;
unsigned char g;
unsigned char b;
};
// 2. Scoped Enum for presets
enum class PresetColor {
Red,
Green,
Blue
};Code language: C++ (cpp)
Expected Output:
Red RGB: (255, 0, 0)
Blue RGB: (0, 0, 255)
+ Hint
- The function signature will be
ColorRGB getColor(PresetColor color). - Use a
switchstatement to map each enumerator to the correctColorRGBliteral, and usereturnto send the structure back to the caller.
+ Show Solution
#include <iostream>
// 1. Structure for color data
struct ColorRGB {
unsigned char r;
unsigned char g;
unsigned char b;
};
// 2. Scoped Enum for presets
enum class PresetColor {
Red,
Green,
Blue
};
// Function that maps enum to struct data
ColorRGB getColor(PresetColor color) {
switch (color) {
case PresetColor::Red:
return {255, 0, 0}; // Initializer list for struct
case PresetColor::Green:
return {0, 255, 0};
case PresetColor::Blue:
return {0, 0, 255};
default:
return {0, 0, 0}; // Black as default
}
}
int main() {
// Call the function to get a struct based on the enum
ColorRGB primary_red = getColor(PresetColor::Red);
ColorRGB primary_blue = getColor(PresetColor::Blue);
std::cout << "Red RGB: (" << (int)primary_red.r << ", "
<< (int)primary_red.g << ", " << (int)primary_red.b << ")" << std::endl;
std::cout << "Blue RGB: (" << (int)primary_blue.r << ", "
<< (int)primary_blue.g << ", " << (int)primary_blue.b << ")" << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- This is a perfect example of using an
enum classto enforce limited, meaningful choices (PresetColor) that drive the creation of complex structured data (ColorRGB). - The function
getColoracts as a mapping layer, converting a type-safe constant into a populated data structure. Note the casts tointwhen printing, asunsigned charmight otherwise be printed as a character instead of a number.
Exercise 26: Advanced Combined Exercise (Employee Pay)
Practice Problem: Define an enum class PayGrade (Junior, Mid, Senior), explicitly setting their underlying integer values to 1, 2, and 3 respectively. Use typedef to alias long long as EmployeeID. Define a structure Employee with an EmployeeID, std::string name, and a PayGrade member. Write a function calculateBonus(const Employee& emp) that uses a switch on the PayGrade to return a bonus amount (e.g., Junior = 1000, Mid = 2500, Senior = 5000).
Expected Output:
Employee: Alice, ID: 10000000001, Bonus: $2500
Employee: Bob, ID: 10000000002, Bonus: $5000
+ Hint
- Define the
PayGradewith the underlying type:enum class PayGrade : int { ... };. - You will need to use
static_cast<int>(emp.grade)in theswitchstatement if you want to switch directly on the integer value, or simply switch on the enum value itself and use the scoped constants.
+ Show Solution
#include <iostream>
#include <string>
// 1. Typedef for data type
typedef long long EmployeeID;
// 2. Scoped Enum Class with explicit base type and values
enum class PayGrade : int {
Junior = 1,
Mid = 2,
Senior = 3
};
// 3. Combined Structure
struct Employee {
EmployeeID id;
std::string name;
PayGrade grade;
};
// Function to calculate bonus based on PayGrade
double calculateBonus(const Employee& emp) {
switch (emp.grade) {
case PayGrade::Junior:
return 1000.00;
case PayGrade::Mid:
return 2500.00;
case PayGrade::Senior:
return 5000.00;
default:
return 0.00;
}
}
int main() {
Employee emp1 = {10000000001LL, "Alice", PayGrade::Mid};
Employee emp2 = {10000000002LL, "Bob", PayGrade::Senior};
std::cout << "Employee: " << emp1.name << ", ID: " << emp1.id
<< ", Bonus: $" << calculateBonus(emp1) << std::endl;
std::cout << "Employee: " << emp2.name << ", ID: " << emp2.id
<< ", Bonus: $" << calculateBonus(emp2) << std::endl;
return 0;
}Code language: C++ (cpp)
Explanation:
- This exercise provides a capstone on the topic.
EmployeeIDusestypedefto create a domain-specific name for a large integer type.PayGradeuses an explicit base type (: int) to confirm its storage size and ensures type safety withenum class. - The
Employeestructure bundles these elements, and thecalculateBonusfunction demonstrates how to use the strongly typed enum to drive financial logic cleanly and reliably.

Leave a Reply