Structures - Creating Custom Data Types
What is a Structure?
Imagine you want to store information about a student. You need:
- Name (string)
- Age (int)
- Grade (double)
You could create three separate variables, but that's messy. A structure (or struct) lets you group related data together into one custom type!
Think of a structure like a form with multiple fields that belong together.
Creating Your First Structure
#include <iostream>
#include <string>
struct Student {
std::string name;
int age;
double grade;
};
int main() {
Student student1;
student1.name = "Alex";
student1.age = 13;
student1.grade = 92.5;
std::cout << "Student Information:" << std::endl;
std::cout << "Name: " << student1.name << std::endl;
std::cout << "Age: " << student1.age << std::endl;
std::cout << "Grade: " << student1.grade << std::endl;
return 0;
}
Output:
Student Information:
Name: Alex
Age: 13
Grade: 92.5
What's happening:
struct Student { ... };defines a new type- Inside are members (variables that belong to the struct)
Student student1;creates a Student variable- Use
.to access members:student1.name
Initializing Structures
Method 1: After Declaration
#include <iostream>
#include <string>
struct Person {
std::string name;
int age;
std::string city;
};
int main() {
Person person1;
person1.name = "Sam";
person1.age = 25;
person1.city = "New York";
std::cout << person1.name << " is " << person1.age;
std::cout << " years old from " << person1.city << std::endl;
return 0;
}
Output:
Sam is 25 years old from New York
Method 2: During Declaration
#include <iostream>
#include <string>
struct Person {
std::string name;
int age;
std::string city;
};
int main() {
Person person1 = {"Sam", 25, "New York"};
std::cout << person1.name << " is " << person1.age;
std::cout << " years old from " << person1.city << std::endl;
return 0;
}
Output:
Sam is 25 years old from New York
Note: Values must be in the same order as declared in the struct!
Multiple Instances
You can create many variables of your custom type:
#include <iostream>
#include <string>
struct Car {
std::string brand;
std::string model;
int year;
};
int main() {
Car car1 = {"Toyota", "Camry", 2020};
Car car2 = {"Honda", "Civic", 2021};
Car car3 = {"Ford", "Mustang", 2022};
std::cout << "Car 1: " << car1.year << " " << car1.brand << " " << car1.model << std::endl;
std::cout << "Car 2: " << car2.year << " " << car2.brand << " " << car2.model << std::endl;
std::cout << "Car 3: " << car3.year << " " << car3.brand << " " << car3.model << std::endl;
return 0;
}
Output:
Car 1: 2020 Toyota Camry
Car 2: 2021 Honda Civic
Car 3: 2022 Ford Mustang
Arrays of Structures
#include <iostream>
#include <string>
struct Book {
std::string title;
std::string author;
int pages;
};
int main() {
Book library[3];
library[0] = {"1984", "George Orwell", 328};
library[1] = {"To Kill a Mockingbird", "Harper Lee", 281};
library[2] = {"The Great Gatsby", "F. Scott Fitzgerald", 180};
std::cout << "Library Books:" << std::endl;
for (int i = 0; i < 3; i++) {
std::cout << (i + 1) << ". " << library[i].title;
std::cout << " by " << library[i].author;
std::cout << " (" << library[i].pages << " pages)" << std::endl;
}
return 0;
}
Output:
Library Books:
1. 1984 by George Orwell (328 pages)
2. To Kill a Mockingbird by Harper Lee (281 pages)
3. The Great Gatsby by F. Scott Fitzgerald (180 pages)
Vectors of Structures
Even better than arrays!
#include <iostream>
#include <vector>
#include <string>
struct Product {
std::string name;
double price;
int quantity;
};
int main() {
std::vector<Product> inventory;
inventory.push_back({"Laptop", 999.99, 5});
inventory.push_back({"Mouse", 29.99, 15});
inventory.push_back({"Keyboard", 79.99, 10});
std::cout << "Inventory:" << std::endl;
for (const Product& item : inventory) {
std::cout << item.name << ": $" << item.price;
std::cout << " (Stock: " << item.quantity << ")" << std::endl;
}
return 0;
}
Output:
Inventory:
Laptop: $999.99 (Stock: 5)
Mouse: $29.99 (Stock: 15)
Keyboard: $79.99 (Stock: 10)
Nested Structures
Structures can contain other structures!
#include <iostream>
#include <string>
struct Date {
int day;
int month;
int year;
};
struct Person {
std::string name;
int age;
Date birthday;
};
int main() {
Person person1;
person1.name = "Alex";
person1.age = 13;
person1.birthday.day = 15;
person1.birthday.month = 6;
person1.birthday.year = 2011;
std::cout << "Name: " << person1.name << std::endl;
std::cout << "Age: " << person1.age << std::endl;
std::cout << "Birthday: " << person1.birthday.day << "/";
std::cout << person1.birthday.month << "/";
std::cout << person1.birthday.year << std::endl;
return 0;
}
Output:
Name: Alex
Age: 13
Birthday: 15/6/2011
Structures with Functions
Passing to Functions
#include <iostream>
#include <string>
struct Rectangle {
double length;
double width;
};
double calculateArea(Rectangle rect) {
return rect.length * rect.width;
}
void printRectangle(Rectangle rect) {
std::cout << "Rectangle: " << rect.length << " x " << rect.width << std::endl;
std::cout << "Area: " << calculateArea(rect) << std::endl;
}
int main() {
Rectangle rect1 = {5.0, 3.0};
Rectangle rect2 = {7.5, 4.2};
printRectangle(rect1);
std::cout << std::endl;
printRectangle(rect2);
return 0;
}
Output:
Rectangle: 5 x 3
Area: 15
Rectangle: 7.5 x 4.2
Area: 31.5
Passing by Reference
#include <iostream>
#include <string>
struct Player {
std::string name;
int score;
int lives;
};
void addPoints(Player& player, int points) {
player.score += points;
}
void loseLife(Player& player) {
player.lives--;
}
void printPlayer(const Player& player) {
std::cout << player.name << " - Score: " << player.score;
std::cout << ", Lives: " << player.lives << std::endl;
}
int main() {
Player player1 = {"Alex", 0, 3};
printPlayer(player1);
addPoints(player1, 100);
printPlayer(player1);
loseLife(player1);
printPlayer(player1);
addPoints(player1, 50);
printPlayer(player1);
return 0;
}
Output:
Alex - Score: 0, Lives: 3
Alex - Score: 100, Lives: 3
Alex - Score: 100, Lives: 2
Alex - Score: 150, Lives: 2
Note: Using & lets functions modify the original struct!
Returning Structures
#include <iostream>
#include <string>
struct Point {
double x;
double y;
};
Point createPoint(double x, double y) {
Point p;
p.x = x;
p.y = y;
return p;
}
Point addPoints(Point p1, Point p2) {
Point result;
result.x = p1.x + p2.x;
result.y = p1.y + p2.y;
return result;
}
int main() {
Point point1 = createPoint(3.0, 4.0);
Point point2 = createPoint(1.0, 2.0);
Point sum = addPoints(point1, point2);
std::cout << "Point 1: (" << point1.x << ", " << point1.y << ")" << std::endl;
std::cout << "Point 2: (" << point2.x << ", " << point2.y << ")" << std::endl;
std::cout << "Sum: (" << sum.x << ", " << sum.y << ")" << std::endl;
return 0;
}
Output:
Point 1: (3, 4)
Point 2: (1, 2)
Sum: (4, 6)
Comparing Structures
You need to compare each member individually:
#include <iostream>
#include <string>
struct Point {
int x;
int y;
};
bool areEqual(const Point& p1, const Point& p2) {
return (p1.x == p2.x && p1.y == p2.y);
}
int main() {
Point point1 = {5, 10};
Point point2 = {5, 10};
Point point3 = {3, 7};
if (areEqual(point1, point2)) {
std::cout << "point1 and point2 are equal" << std::endl;
}
if (!areEqual(point1, point3)) {
std::cout << "point1 and point3 are different" << std::endl;
}
return 0;
}
Output:
point1 and point2 are equal
point1 and point3 are different
Real-World Example: Contact Book
#include <iostream>
#include <vector>
#include <string>
struct Contact {
std::string name;
std::string phone;
std::string email;
};
void addContact(std::vector<Contact>& contacts) {
Contact newContact;
std::cout << "Enter name: ";
std::cin.ignore();
std::getline(std::cin, newContact.name);
std::cout << "Enter phone: ";
std::getline(std::cin, newContact.phone);
std::cout << "Enter email: ";
std::getline(std::cin, newContact.email);
contacts.push_back(newContact);
std::cout << "Contact added!" << std::endl;
}
void displayContacts(const std::vector<Contact>& contacts) {
if (contacts.empty()) {
std::cout << "No contacts yet!" << std::endl;
return;
}
std::cout << "\n=== All Contacts ===" << std::endl;
for (int i = 0; i < contacts.size(); i++) {
std::cout << (i + 1) << ". " << contacts[i].name << std::endl;
std::cout << " Phone: " << contacts[i].phone << std::endl;
std::cout << " Email: " << contacts[i].email << std::endl;
}
}
int main() {
std::vector<Contact> contacts;
while (true) {
std::cout << "\n=== Contact Book ===" << std::endl;
std::cout << "1. Add Contact" << std::endl;
std::cout << "2. View All Contacts" << std::endl;
std::cout << "3. Exit" << std::endl;
std::cout << "Choice: ";
int choice;
std::cin >> choice;
if (choice == 1) {
addContact(contacts);
} else if (choice == 2) {
displayContacts(contacts);
} else if (choice == 3) {
std::cout << "Goodbye!" << std::endl;
break;
} else {
std::cout << "Invalid choice!" << std::endl;
}
}
return 0;
}
Practical Example: Student Grade System
#include <iostream>
#include <vector>
#include <string>
struct Student {
std::string name;
int rollNumber;
double grade;
};
void addStudent(std::vector<Student>& students) {
Student newStudent;
std::cout << "Enter student name: ";
std::cin.ignore();
std::getline(std::cin, newStudent.name);
std::cout << "Enter roll number: ";
std::cin >> newStudent.rollNumber;
std::cout << "Enter grade: ";
std::cin >> newStudent.grade;
students.push_back(newStudent);
std::cout << "Student added!" << std::endl;
}
void displayStudents(const std::vector<Student>& students) {
if (students.empty()) {
std::cout << "No students yet!" << std::endl;
return;
}
std::cout << "\n=== All Students ===" << std::endl;
for (const Student& s : students) {
std::cout << "Roll #" << s.rollNumber << ": " << s.name;
std::cout << " (Grade: " << s.grade << ")" << std::endl;
}
}
double calculateAverage(const std::vector<Student>& students) {
if (students.empty()) return 0.0;
double sum = 0;
for (const Student& s : students) {
sum += s.grade;
}
return sum / students.size();
}
Student findTopStudent(const std::vector<Student>& students) {
Student top = students[0];
for (const Student& s : students) {
if (s.grade > top.grade) {
top = s;
}
}
return top;
}
int main() {
std::vector<Student> students;
while (true) {
std::cout << "\n=== Student Grade System ===" << std::endl;
std::cout << "1. Add Student" << std::endl;
std::cout << "2. View All Students" << std::endl;
std::cout << "3. Class Average" << std::endl;
std::cout << "4. Top Student" << std::endl;
std::cout << "5. Exit" << std::endl;
std::cout << "Choice: ";
int choice;
std::cin >> choice;
if (choice == 1) {
addStudent(students);
} else if (choice == 2) {
displayStudents(students);
} else if (choice == 3) {
if (students.empty()) {
std::cout << "No students yet!" << std::endl;
} else {
std::cout << "Class average: " << calculateAverage(students) << std::endl;
}
} else if (choice == 4) {
if (students.empty()) {
std::cout << "No students yet!" << std::endl;
} else {
Student top = findTopStudent(students);
std::cout << "Top student: " << top.name;
std::cout << " (Grade: " << top.grade << ")" << std::endl;
}
} else if (choice == 5) {
std::cout << "Goodbye!" << std::endl;
break;
} else {
std::cout << "Invalid choice!" << std::endl;
}
}
return 0;
}
Common Mistakes
Mistake 1: Forgetting Semicolon After Struct
struct Person {
std::string name;
int age;
}
Should be:
struct Person {
std::string name;
int age;
};
Note the semicolon after the closing brace!
Mistake 2: Wrong Member Access
Student student1;
student1->name = "Alex";
Use . not ->:
student1.name = "Alex";
We'll learn about -> when we study pointers!
Mistake 3: Not Initializing Members
struct Point {
int x;
int y;
};
Point p;
std::cout << p.x;
x has garbage value! Always initialize:
Point p = {0, 0};
Practice Exercises
1. Movie Database Create a struct for movies (title, director, year, rating). Let users add movies and search by title.
2. Bank Account System Create a struct for accounts (account number, holder name, balance). Implement deposit and withdraw functions.
3. Inventory Manager Create a struct for products (name, price, stock). Calculate total inventory value.
Example solution for bank account:
#include <iostream>
#include <string>
struct Account {
int accountNumber;
std::string holderName;
double balance;
};
void deposit(Account& acc, double amount) {
acc.balance += amount;
std::cout << "Deposited $" << amount << std::endl;
}
void withdraw(Account& acc, double amount) {
if (amount > acc.balance) {
std::cout << "Insufficient funds!" << std::endl;
} else {
acc.balance -= amount;
std::cout << "Withdrew $" << amount << std::endl;
}
}
void displayAccount(const Account& acc) {
std::cout << "\n=== Account Info ===" << std::endl;
std::cout << "Account #: " << acc.accountNumber << std::endl;
std::cout << "Holder: " << acc.holderName << std::endl;
std::cout << "Balance: $" << acc.balance << std::endl;
}
int main() {
Account myAccount = {12345, "Alex Smith", 1000.0};
displayAccount(myAccount);
deposit(myAccount, 500);
displayAccount(myAccount);
withdraw(myAccount, 200);
displayAccount(myAccount);
return 0;
}
What's Next?
Now you can create custom data types! Next, we'll learn about:
- Classes - Like structures but with superpowers!
- Object-Oriented Programming - A whole new way to think about code
- Encapsulation, methods, and more!
You're ready for advanced programming! 🚀