C++: Practice: Address Book System
Last updated: 2026-08-26
In lesson 50, we learned about unit testing.
Now, we'll build our first comprehensive practical project — an address book system.
This project will integrate all the knowledge you've learned so far.
1. Project Requirements
(1) 1.1 Functional Requirements
| Feature | Description |
|---|---|
| Add contact | Enter name, phone, email |
| Delete contact | Delete by name or phone |
| Modify contact | Update information |
| Find contact | Search by name or phone |
| Display all | List all contacts |
| Save/Load | Persist to file |
(2) 1.2 Class Design
Contact
- name, phone, email
AddressBook
- vector<Contact> contacts
- add, remove, update, find, display
- save, load
2. Contact Class
(1) 2.1 Contact Class Definition
#include <iostream>
#include <string>
#include <fstream>
class Contact {
private:
std::string name;
std::string phone;
std::string email;
public:
Contact() = default;
Contact(const std::string& name, const std::string& phone, const std::string& email)
: name(name), phone(phone), email(email) {}
// Getter
std::string getName() const { return name; }
std::string getPhone() const { return phone; }
std::string getEmail() const { return email; }
// Setter
void setName(const std::string& n) { name = n; }
void setPhone(const std::string& p) { phone = p; }
void setEmail(const std::string& e) { email = e; }
// Display
void display() const {
std::cout << "Name: " << name << std::endl;
std::cout << "Phone: " << phone << std::endl;
std::cout << "Email: " << email << std::endl;
std::cout << "-------------------" << std::endl;
}
// Serialize (save to file)
void save(std::ofstream& file) const {
file << name << "," << phone << "," << email << std::endl;
}
// Deserialize (load from file)
static Contact load(std::ifstream& file) {
Contact c;
std::getline(file, c.name, ',');
std::getline(file, c.phone, ',');
std::getline(file, c.email);
return c;
}
};
3. Address Book Class
(1) 3.1 AddressBook Class Definition
▶ Example 1: Using STL Containers (Difficulty ⭐)
#include <vector>
#include <algorithm>
class AddressBook {
private:
std::vector<Contact> contacts;
public:
// Add contact
void addContact(const Contact& c) {
contacts.push_back(c);
std::cout << "Added successfully!" << std::endl;
}
// Find contact (by name)
Contact* findByName(const std::string& name) {
for (auto& c : contacts) {
if (c.getName() == name) {
return &c;
}
}
return nullptr;
}
// Delete contact (by name)
bool removeByName(const std::string& name) {
auto it = std::remove_if(contacts.begin(), contacts.end(),
[&name](const Contact& c) {
return c.getName() == name;
});
if (it != contacts.end()) {
contacts.erase(it, contacts.end());
std::cout << "Deleted successfully!" << std::endl;
return true;
}
std::cout << "Contact not found: " << name << std::endl;
return false;
}
// Display all contacts
void displayAll() const {
if (contacts.empty()) {
std::cout << "Address book is empty" << std::endl;
return;
}
for (const auto& c : contacts) {
c.display();
}
}
// Save to file
void saveToFile(const std::string& filename) const {
std::ofstream file(filename);
if (!file) {
std::cerr << "Cannot open file" << std::endl;
return;
}
for (const auto& c : contacts) {
c.save(file);
}
file.close();
std::cout << "Saved successfully!" << std::endl;
}
// Load from file
void loadFromFile(const std::string& filename) {
std::ifstream file(filename);
if (!file) {
std::cerr << "Cannot open file" << std::endl;
return;
}
contacts.clear(); // Clear existing data
std::string line;
while (file.peek() != EOF) {
contacts.push_back(Contact::load(file));
}
file.close();
std::cout << "Loaded successfully!" << std::endl;
}
};
Output:
Added successfully!
Deleted successfully!
Contact not found:
Address book is empty
Saved successfully!
Loaded successfully!
4. Main Menu
(1) 4.1 Menu Implementation
void showMenu() {
### ▶ Example 2: Basic Programming Practice (Difficulty ⭐)
std::cout << "\n===== Address Book Management System =====" << std::endl;
std::cout << "1. Add contact" << std::endl;
std::cout << "2. Delete contact" << std::endl;
std::cout << "3. Find contact" << std::endl;
std::cout << "4. Display all contacts" << std::endl;
std::cout << "5. Save" << std::endl;
std::cout << "6. Load" << std::endl;
std::cout << "0. Exit" << std::endl;
std::cout << "==========================================" << std::endl;
std::cout << "Choose: ";
}
int main() {
AddressBook book;
int choice;
do {
showMenu();
std::cin >> choice;
switch (choice) {
case 1: {
std::string name, phone, email;
std::cout << "Name: ";
std::cin >> name;
std::cout << "Phone: ";
std::cin >> phone;
std::cout << "Email: ";
std::cin >> email;
book.addContact(Contact(name, phone, email));
break;
}
case 2: {
std::string name;
std::cout << "Name: ";
std::cin >> name;
book.removeByName(name);
break;
}
case 3: {
std::string name;
std::cout << "Name: ";
std::cin >> name;
Contact* c = book.findByName(name);
if (c) {
c->display();
} else {
std::cout << "Not found" << std::endl;
}
break;
}
case 4:
book.displayAll();
break;
case 5: {
book.saveToFile("contacts.txt");
break;
}
case 6: {
book.loadFromFile("contacts.txt");
break;
}
case 0:
std::cout << "Goodbye!" << std::endl;
break;
default:
std::cout << "Invalid choice" << std::endl;
}
} while (choice != 0);
return 0;
}
5. Extension Suggestions
(1) 5.1 Feature Extensions
| Feature | Difficulty |
|---|---|
| Search by phone | ⭐ |
| Modify contact | ⭐⭐ |
| Sort by name | ⭐⭐ |
| Import/Export CSV | ⭐⭐⭐ |
| GUI | ⭐⭐⭐⭐ |
❓ Exercises
(1) Basic Exercise (Difficulty ⭐)
Add a "search by phone" feature to the address book.
(2) Intermediate Exercise (Difficulty ⭐⭐)
Add a "modify contact" feature to the address book.
(3) Challenge Exercise (Difficulty ⭐⭐⭐)
Refactor the address book using std::map to improve search efficiency.
▶ Example 3: Contact Struct Definition (Difficulty ⭐)
#include <iostream>
#include <string>
struct Contact {
std::string name;
std::string phone;
std::string email;
void display() const {
std::cout << "Name: " << name << std::endl;
std::cout << "Phone: " << phone << std::endl;
std::cout << "Email: " << email << std::endl;
}
};
int main() {
Contact c1 = {"Zhang San", "13800138000", "zhangsan@example.com"};
Contact c2 = {"Li Si", "13900139000", "lisi@example.com"};
c1.display();
std::cout << "---" << std::endl;
c2.display();
return 0;
}
Output:
Name:
Phone:
Email:
---
❓ FAQ
📖 Summary
| Knowledge Point | Application |
|---|---|
| Object-Oriented | Contact and AddressBook classes |
| STL | vector for storing contacts |
| File Operations | Save/Load |
| String Processing | Parse CSV |
- Address book system: four core CRUD operations
- Use structs to store contact information
- Vector container for managing dynamic data
- File I/O for data persistence
- Modular functions encapsulate each feature
📝 Exercises
-
Basic (Difficulty ⭐): Run the address book program, add 3 contacts (name, phone, group), and view the display. Try using the "edit" feature to modify one contact's information.
-
Intermediate (Difficulty ⭐⭐): Add a "favorite contact" feature to the address book — add a
bool isFavoritefield to the struct, and mark favorite contacts with[★]when displaying the list. -
Challenge (Difficulty ⭐⭐⭐): Implement a "fuzzy search" feature: after the user enters a keyword, match all contacts whose names contain the keyword and display them. If the input is empty, show all contacts. Support case-insensitive matching.
Next lesson: Practice: Simple Database (#52)