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

TEXT 📖 Display only
Contact
 - name, phone, email

AddressBook
 - vector<Contact> contacts
 - add, remove, update, find, display
 - save, load


2. Contact Class

(1) 2.1 Contact Class Definition

TEXT 📖 Display only
#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 ⭐)

CPP 📖 Display only
#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;
	}
};
65 logic lines (exceeds 40-line limit, display only)

Output:

TEXT 📖 Display only
Added successfully!
Deleted successfully!
Contact not found:
Address book is empty
Saved successfully!
Loaded successfully!


4. Main Menu

(1) 4.1 Menu Implementation

TEXT 📖 Display only
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 ⭐)

CPP
#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;
}
▶ Try it Yourself

Output:

TEXT 📖 Display only
Name:
Phone:
Email:
---

❓ FAQ

Q Why use vector instead of arrays?
A vector automatically resizes, so you don't need to know the number of elements in advance. Array size must be determined at compile time, while vector can flexibly grow and shrink at runtime.
Q Why use a struct for contact info instead of multiple arrays?
A Structs package related data together, making the logic clearer. With multiple arrays, add/delete operations are error-prone (e.g., deleting a name but forgetting to delete the phone).
Q What should I watch out for with file I/O?
A ① Check if the file opened successfully (is_open); ② Close after writing (close()); ③ Use eof() or good() in read loops to avoid infinite loops; ④ Use exception handling to ensure files are properly closed.

📖 Summary

Knowledge Point Application
Object-Oriented Contact and AddressBook classes
STL vector for storing contacts
File Operations Save/Load
String Processing Parse CSV

📝 Exercises

  1. 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.

  2. Intermediate (Difficulty ⭐⭐): Add a "favorite contact" feature to the address book — add a bool isFavorite field to the struct, and mark favorite contacts with [★] when displaying the list.

  3. 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)

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏