C++: تمرين: نظام دفتر العناوين
آخر تحديث: 2026-08-26
في الدرس 50، تعلمنا عن اختبار الوحدات.
الآن، سنبني أول مشروع عملي شامل لنا — نظام دفتر عناوين.
سيدمج هذا المشروع كل المعارف التي تعلمتها حتى الآن.
1. متطلبات المشروع
(1) 1.1 المتطلبات الوظيفية
| الميزة | الوصف |
|---|---|
| إضافة جهة اتصال | إدخال الاسم، الهاتف، البريد الإلكتروني |
| حذف جهة اتصال | الحذف بالاسم أو الهاتف |
| تعديل جهة اتصال | تحديث المعلومات |
| البحث عن جهة اتصال | البحث بالاسم أو الهاتف |
| عرض الكل | عرض جميع جهات الاتصال |
| حفظ/تحميل | التخزين المستمر في ملف |
(2) 1.2 تصميم الأصناف
Contact
- name, phone, email
AddressBook
- vector<Contact> contacts
- add, remove, update, find, display
- save, load
2. صنف جهة الاتصال
(1) 2.1 تعريف صنف Contact
#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. صنف دفتر العناوين
(1) 3.1 تعريف صنف AddressBook
▶ مثال 1: استخدام حاويات STL (الصعوبة ⭐)
#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;
}
};
المخرجات:
Added successfully!
Deleted successfully!
Contact not found:
Address book is empty
Saved successfully!
Loaded successfully!
4. القائمة الرئيسية
(1) 4.1 تنفيذ القائمة
void showMenu() {
### ▶ مثال 2: تمرين برمجة أساسي (الصعوبة ⭐)
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. اقتراحات التوسعة
(1) 5.1 توسيع الميزات
| الميزة | الصعوبة |
|---|---|
| البحث بالهاتف | ⭐ |
| تعديل جهة اتصال | ⭐⭐ |
| الترتيب حسب الاسم | ⭐⭐ |
| استيراد/تصدير CSV | ⭐⭐⭐ |
| واجهة رسومية | ⭐⭐⭐⭐ |
❓ تمارين
(1) تمرين أساسي (الصعوبة ⭐)
أضف ميزة "البحث بالهاتف" إلى دفتر العناوين.
(2) تمرين متوسط (الصعوبة ⭐⭐)
أضف ميزة "تعديل جهة اتصال" إلى دفتر العناوين.
(3) تمرين تحدي (الصعوبة ⭐⭐⭐)
أعد هيكلة دفتر العناوين باستخدام std::map لتحسين كفاءة البحث.
▶ مثال 3: تعريف بنية Contact (الصعوبة ⭐)
#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;
}
المخرجات:
Name:
Phone:
Email:
---
❓ أسئلة شائعة
📖 ملخص
| نقطة المعرفة | التطبيق |
|---|---|
| البرمجة كائنية التوجه | صنفا Contact و AddressBook |
| STL | vector لتخزين جهات الاتصال |
| عمليات الملفات | حفظ/تحميل |
| معالجة السلاسل النصية | تحليل CSV |
- نظام دفتر العناوين: أربع عمليات CRUD الأساسية
- استخدام البنى لتخزين معلومات جهات الاتصال
- حاوية vector لإدارة البيانات الديناميكية
- إدخال/إخراج الملفات للتخزين المستمر للبيانات
- دوال نمطية تغلف كل ميزة
📝 تمارين
-
أساسي (الصعوبة ⭐): شغّل برنامج دفتر العناوين، أضف 3 جهات اتصال (الاسم، الهاتف، المجموعة)، واعرض النتيجة. جرب استخدام ميزة "التعديل" لتعديل معلومات جهة اتصال واحدة.
-
متوسط (الصعوبة ⭐⭐): أضف ميزة "جهة الاتصال المفضلة" إلى دفتر العناوين — أضف حقل
bool isFavoriteإلى البنية، وعلّم جهات الاتصال المفضلة بـ[★]عند عرض القائمة. -
تحدي (الصعوبة ⭐⭐⭐): نفّذ ميزة "البحث التقريبي": بعد أن يدخل المستخدم كلمة مفتاحية، طابق جميع جهات الاتصال التي تحتوي أسماؤها على الكلمة المفتاحية واعرضها. إذا كان الإدخال فارغاً، اعرض جميع جهات الاتصال. ادعم المطابقة غير الحساسة لحالة الأحرف.
الدرس التالي: تمرين: قاعدة بيانات بسيطة (#52)