0

0

C++如何实现简单的通讯录管理系统

P粉602998670

P粉602998670

发布时间:2025-09-16 10:37:01

|

320人浏览过

|

来源于php中文网

原创

首先定义Contact类封装联系人信息,再通过AddressBookManager类用std::vector管理联系人,实现增删改查及文件持久化功能。

c++如何实现简单的通讯录管理系统

C++实现一个简单的通讯录管理系统,核心思路其实就是用类来封装联系人信息,然后用一个容器(比如

std::vector
)来存放这些联系人对象,最后通过一系列函数来对这个容器进行增删改查操作。这听起来可能有点抽象,但实践起来,就是围绕着“数据结构”和“操作逻辑”这两个点展开。

解决方案

要构建一个C++通讯录管理系统,我们通常会从定义联系人的数据结构开始,然后是管理这些联系人的核心类,最后是用户交互界面。

  1. 联系人数据结构 (Contact Class) 创建一个

    Contact
    类来表示一个联系人。这个类应该包含联系人的基本信息,比如姓名、电话号码、电子邮件和地址。

    #include 
    #include 
    #include 
    #include  // 用于文件操作
    #include   // 用于清理输入缓冲区
    
    class Contact {
    public:
        std::string name;
        std::string phoneNumber;
        std::string email;
        std::string address;
    
        // 默认构造函数
        Contact() = default;
    
        // 带参数的构造函数
        Contact(const std::string& name, const std::string& phone,
                const std::string& email = "", const std::string& address = "")
            : name(name), phoneNumber(phone), email(email), address(address) {}
    
        // 显示联系人信息
        void display() const {
            std::cout << "姓名: " << name << std::endl;
            std::cout << "电话: " << phoneNumber << std::endl;
            if (!email.empty()) std::cout << "邮箱: " << email << std::endl;
            if (!address.empty()) std::cout << "地址: " << address << std::endl;
            std::cout << "--------------------" << std::endl;
        }
    
        // 方便保存到文件
        std::string toStringForFile() const {
            return name + "|" + phoneNumber + "|" + email + "|" + address;
        }
    
        // 从文件字符串解析
        static Contact fromStringForFile(const std::string& line) {
            Contact c;
            size_t pos = 0;
            size_t next_pos;
    
            next_pos = line.find('|', pos);
            c.name = line.substr(pos, next_pos - pos);
            pos = next_pos + 1;
    
            next_pos = line.find('|', pos);
            c.phoneNumber = line.substr(pos, next_pos - pos);
            pos = next_pos + 1;
    
            next_pos = line.find('|', pos);
            c.email = line.substr(pos, next_pos - pos);
            pos = next_pos + 1;
    
            c.address = line.substr(pos);
            return c;
        }
    };
  2. 通讯录管理类 (AddressBookManager Class) 这个类将负责存储

    Contact
    对象,并提供增、删、改、查以及数据持久化的功能。

    class AddressBookManager {
    private:
        std::vector contacts;
        std::string filename = "contacts.txt"; // 数据存储文件名
    
        void clearInputBuffer() {
            std::cin.ignore(std::numeric_limits::max(), '\n');
        }
    
    public:
        AddressBookManager() {
            loadContacts(); // 构造时尝试加载数据
        }
    
        ~AddressBookManager() {
            saveContacts(); // 析构时保存数据
        }
    
        // 添加联系人
        void addContact() {
            std::string name, phone, email, address;
            std::cout << "请输入姓名: ";
            std::cin >> name;
            std::cout << "请输入电话号码: ";
            std::cin >> phone;
            clearInputBuffer(); // 清理缓冲区,防止getline读取到换行符
            std::cout << "请输入邮箱 (可选): ";
            std::getline(std::cin, email);
            std::cout << "请输入地址 (可选): ";
            std::getline(std::cin, address);
    
            contacts.emplace_back(name, phone, email, address);
            std::cout << "联系人添加成功!" << std::endl;
        }
    
        // 显示所有联系人
        void displayAllContacts() const {
            if (contacts.empty()) {
                std::cout << "通讯录为空。" << std::endl;
                return;
            }
            std::cout << "\n----- 所有联系人 -----" << std::endl;
            for (const auto& contact : contacts) {
                contact.display();
            }
            std::cout << "--------------------" << std::endl;
        }
    
        // 查找联系人
        void searchContact() const {
            if (contacts.empty()) {
                std::cout << "通讯录为空,无法查找。" << std::endl;
                return;
            }
            std::string keyword;
            std::cout << "请输入姓名或电话号码进行查找: ";
            std::cin >> keyword;
            clearInputBuffer();
    
            bool found = false;
            std::cout << "\n----- 查找结果 -----" << std::endl;
            for (const auto& contact : contacts) {
                if (contact.name.find(keyword) != std::string::npos ||
                    contact.phoneNumber.find(keyword) != std::string::npos) {
                    contact.display();
                    found = true;
                }
            }
            if (!found) {
                std::cout << "未找到匹配的联系人。" << std::endl;
            }
            std::cout << "--------------------" << std::endl;
        }
    
        // 修改联系人
        void modifyContact() {
            if (contacts.empty()) {
                std::cout << "通讯录为空,无法修改。" << std::endl;
                return;
            }
            std::string nameToModify;
            std::cout << "请输入要修改的联系人姓名: ";
            std::cin >> nameToModify;
            clearInputBuffer();
    
            bool found = false;
            for (auto& contact : contacts) {
                if (contact.name == nameToModify) {
                    std::cout << "找到联系人: " << contact.name << std::endl;
                    std::cout << "请输入新的电话号码 (当前: " << contact.phoneNumber << "): ";
                    std::getline(std::cin, contact.phoneNumber);
                    std::cout << "请输入新的邮箱 (当前: " << contact.email << "): ";
                    std::getline(std::cin, contact.email);
                    std::cout << "请输入新的地址 (当前: " << contact.address << "): ";
                    std::getline(std::cin, contact.address);
                    std::cout << "联系人修改成功!" << std::endl;
                    found = true;
                    break;
                }
            }
            if (!found) {
                std::cout << "未找到姓名为 '" << nameToModify << "' 的联系人。" << std::endl;
            }
        }
    
        // 删除联系人
        void deleteContact() {
            if (contacts.empty()) {
                std::cout << "通讯录为空,无法删除。" << std::endl;
                return;
            }
            std::string nameToDelete;
            std::cout << "请输入要删除的联系人姓名: ";
            std::cin >> nameToDelete;
            clearInputBuffer();
    
            auto it = contacts.begin();
            bool found = false;
            while (it != contacts.end()) {
                if (it->name == nameToDelete) {
                    it = contacts.erase(it); // 删除并获取下一个迭代器
                    std::cout << "联系人删除成功!" << std::endl;
                    found = true;
                    break;
                } else {
                    ++it;
                }
            }
            if (!found) {
                std::cout << "未找到姓名为 '" << nameToDelete << "' 的联系人。" << std::endl;
            }
        }
    
        // 保存联系人到文件
        void saveContacts() const {
            std::ofstream outFile(filename);
            if (!outFile.is_open()) {
                std::cerr << "错误:无法打开文件 " << filename << " 进行写入。" << std::endl;
                return;
            }
            for (const auto& contact : contacts) {
                outFile << contact.toStringForFile() << std::endl;
            }
            outFile.close();
            // std::cout << "通讯录已保存到文件。" << std::endl; // 运行时不频繁提示
        }
    
        // 从文件加载联系人
        void loadContacts() {
            std::ifstream inFile(filename);
            if (!inFile.is_open()) {
                // std::cerr << "提示:文件 " << filename << " 不存在或无法打开,将创建新通讯录。" << std::endl;
                return; // 文件不存在是正常情况,初次运行会创建
            }
            std::string line;
            while (std::getline(inFile, line)) {
                if (!line.empty()) {
                    contacts.push_back(Contact::fromStringForFile(line));
                }
            }
            inFile.close();
            // std::cout << "通讯录已从文件加载。" << std::endl; // 运行时不频繁提示
        }
    };
  3. 主程序 (main function)

    main
    函数中,创建一个
    AddressBookManager
    对象,并实现一个菜单驱动的循环,让用户选择不同的操作。

    void showMenu() {
        std::cout << "\n----- 通讯录管理系统 -----" << std::endl;
        std::cout << "1. 添加联系人" << std::endl;
        std::cout << "2. 显示所有联系人" << std::endl;
        std::cout << "3. 查找联系人" << std::endl;
        std::cout << "4. 修改联系人" << std::endl;
        std::cout << "5. 删除联系人" << std::endl;
        std::cout << "0. 退出" << std::endl;
        std::cout << "-------------------------" << std::endl;
        std::cout << "请选择操作: ";
    }
    
    int main() {
        AddressBookManager manager;
        int choice;
    
        do {
            showMenu();
            std::cin >> choice;
    
            // 处理输入错误,防止无限循环
            if (std::cin.fail()) {
                std::cout << "无效输入,请重新输入数字。" << std::endl;
                std::cin.clear(); // 清除错误标志
                std::cin.ignore(std::numeric_limits::max(), '\n'); // 忽略剩余输入
                continue;
            }
    
            switch (choice) {
                case 1: manager.addContact(); break;
                case 2: manager.displayAllContacts(); break;
                case 3: manager.searchContact(); break;
                case 4: manager.modifyContact(); break;
                case 5: manager.deleteContact(); break;
                case 0: std::cout << "感谢使用,再见!" << std::endl; break;
                default: std::cout << "无效选择,请重新输入。" << std::endl; break;
            }
        } while (choice != 0);
    
        return 0;
    }

    这个解决方案涵盖了通讯录的基本功能,并且考虑了数据持久化,使得程序关闭后数据不会丢失。

在C++中,设计一个联系人数据结构时,有哪些关键考量?

设计联系人数据结构,其实就是决定一个

Contact
类里面要放些什么,以及这些东西该用什么类型。从我个人经验来看,这不单单是把字段堆砌起来,更要考虑后续的扩展性、易用性,还有一些实际操作中的小细节。

立即学习C++免费学习笔记(深入)”;

首先,核心字段肯定少不了:姓名、电话号码是必须的。姓名用

std::string
毫无疑问,电话号码我个人也倾向于用
std::string
为什么不用
long long
或者其他数字类型呢?原因很简单:电话号码可能包含区号前的
+
号、括号、横线等非数字字符,而且国内的电话号码以0开头,如果用数字类型存储,这个0就会被自动省略,这显然是不对的。此外,电话号码本身很少需要进行数值运算,所以字符串是最合适的选择。

其次,可选字段像电子邮件和地址,也应该用

std::string
。这些信息可能不是每个联系人都具备,所以在构造函数或者添加联系人时,应该允许它们为空。在
Contact
类里,我通常会给它们设置默认值为空字符串,这样在显示时,如果为空就可以选择不显示,让输出更整洁。

再者,封装性。虽然对于一个简单的系统,把所有成员变量设为

public
可能更直接,但从良好的编程习惯和未来扩展的角度看,使用
private
成员变量并通过
public
的getter/setter方法来访问和修改,会更好。这样可以控制数据的有效性,比如在setter里加入数据校验逻辑。不过,对于这个“简单”通讯录,我直接用了
public
,图个方便,毕竟是快速实现嘛。

华友协同办公自动化OA系统
华友协同办公自动化OA系统

华友协同办公管理系统(华友OA),基于微软最新的.net 2.0平台和SQL Server数据库,集成强大的Ajax技术,采用多层分布式架构,实现统一办公平台,功能强大、价格便宜,是适用于企事业单位的通用型网络协同办公系统。 系统秉承协同办公的思想,集成即时通讯、日记管理、通知管理、邮件管理、新闻、考勤管理、短信管理、个人文件柜、日程安排、工作计划、工作日清、通讯录、公文流转、论坛、在线调查、

下载

还有一点,就是唯一标识符。现在这个简单系统是靠姓名来识别联系人的,但现实中,重名的情况并不少见。如果通讯录规模稍大,或者对数据一致性要求高,我就会考虑给每个联系人添加一个唯一的ID(比如

int
UUID
)。这样在修改或删除时,就可以通过ID来精确操作,避免了重名带来的混淆。这个ID可以由系统自动生成,比如一个递增的整数。

最后,操作符重载也是一个可以考虑的点。比如重载

<<
操作符,让
std::cout << myContact;
就能直接打印出联系人的完整信息,这会使得代码更加简洁和易读。不过,在上面的示例中,我只是提供了一个
display()
方法,这对于初学者来说可能更直观一些。

总的来说,设计一个数据结构,更多的是在考虑“它要承载什么信息”、“这些信息怎么最恰当地存储”、“未来可能有哪些操作会用到它”,以及“如何让它用起来更顺手”。

如何高效地实现通讯录的增删改查功能?

高效实现通讯录的增删改查(CRUD)功能,对于一个简单的C++通讯录来说,关键在于选择合适的数据结构来存储联系人,以及如何编写这些操作的逻辑。

就我个人经验而言,对于这种规模不大的通讯录(比如几十、几百个联系人),

std::vector
是一个非常好的选择。它使用起来非常直观,而且C++标准库已经为它优化了内存管理和许多基本操作。

  • 增加 (Add) 联系人: 这个操作是

    std::vector
    的强项。当用户输入完联系人信息后,我们创建一个
    Contact
    对象,然后直接调用
    contacts.push_back(newContact);
    push_back
    会在
    vector
    的末尾添加元素,通常效率很高(平均O(1),最坏O(N)当需要重新分配内存时)。这没什么可纠结的,直接用就好。

  • 显示 (Display) 所有联系人: 这也很直接,就是遍历

    std::vector
    。你可以用基于范围的for循环
    for (const auto& contact : contacts)
    ,或者传统的迭代器循环。遍历并调用每个
    Contact
    对象的
    display()
    方法即可。这个操作的复杂度是O(N),N是联系人数量,这是不可避免的,因为你得显示所有信息。

  • 查找 (Search) 联系人: 这是CRUD操作中效率考量比较多的地方。对于

    std::vector
    ,最直接的方式就是线性查找。你可以遍历
    vector
    ,检查每个联系人的姓名或电话号码是否包含用户输入的关键词。比如:

    for (const auto& contact : contacts) {
        if (contact.name.find(keyword) != std::string::npos ||
            contact.phoneNumber.find(keyword) != std::string::npos) {
            // 找到并显示
        }
    }

    std::string::find
    会返回
    std::string::npos
    如果没找到子串。这种方式简单易懂,对于小规模数据,其O(N)的复杂度完全可以接受。如果联系人数量巨大,线性查找就会变得很慢,那时我们会考虑
    std::map
    std::unordered_map
    ,它们能提供O(logN)或平均O(1)的查找速度,但那会增加系统的复杂性,需要选择一个唯一的键(比如联系人姓名或ID)。对于“简单”通讯录,没必要过度优化。

  • 修改 (Modify) 联系人: 修改操作通常是先查找,再修改。用户输入要修改的联系人姓名(或ID),然后我们遍历

    vector
    找到对应的
    Contact
    对象。一旦找到,直接修改这个对象的成员变量即可。

    for (auto& contact : contacts) { // 注意这里是引用,以便修改
        if (contact.name == nameToModify) {
            // 获取新数据并更新 contact.phoneNumber, contact.email 等
            break; // 找到并修改后就可以退出循环了
        }
    }

    同样,查找部分是O(N),修改本身是O(1)。

  • 删除 (Delete) 联系人: 删除操作稍微有点讲究。找到要删除的联系人后,我们不能直接从

    vector
    中“抠掉”它。
    std::vector
    提供了
    erase()
    方法。

    auto it = contacts.begin();
    while (it != contacts.end()) {
        if (it->name ==

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

317

2023.08.02

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

180

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

279

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

253

2025.06.11

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

121

2025.08.07

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

524

2023.09.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

257

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.09.04

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

27

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号