0

0

怎样用C++实现简易通讯录管理 vector容器存储联系人信息

P粉602998670

P粉602998670

发布时间:2025-07-06 11:04:01

|

303人浏览过

|

来源于php中文网

原创

c++++实现简易通讯录的核心思路是定义结构体或类表示联系人,使用std::vector存储对象,并编写添加、显示、搜索和删除功能。2. 使用std::vector是因为其动态数组特性,能自动调整大小,支持连续存储和高效遍历,适合数据量较小的场景。3. 搜索与删除挑战包括线性查找效率低、频繁删除导致元素移动开销大,优化方案包括排序后二分查找、使用哈希表提升查找速度、按需选择合适的数据结构。4. 提升用户友好性和健壮性的方法包括提供清晰菜单提示、友好的反馈信息、处理空列表情况、验证输入合法性、支持完整字符串输入,确保程序稳定不易崩溃。

怎样用C++实现简易通讯录管理 vector容器存储联系人信息

用C++实现简易通讯录,核心思路是定义一个结构体或类来表示联系人信息,然后利用std::vector容器来存储这些联系人对象。通过编写添加、显示、搜索和删除等函数,并结合一个简单的菜单循环,就能搭建起一个基本的通讯录管理系统。

怎样用C++实现简易通讯录管理 vector容器存储联系人信息

解决方案

要构建这样一个简易通讯录,我们首先需要一个结构来表示单个联系人。一个struct Contact包含姓名、电话和邮箱等字段就足够了。

怎样用C++实现简易通讯录管理 vector容器存储联系人信息
#include 
#include 
#include 
#include  // For numeric_limits

// 定义联系人结构体
struct Contact {
    std::string name;
    std::string phone;
    std::string email;

    // 构造函数,方便初始化
    Contact(std::string n, std::string p, std::string e) : name(std::move(n)), phone(std::move(p)), email(std::move(e)) {}

    // 打印联系人信息
    void print() const {
        std::cout << "姓名: " << name << ", 电话: " << phone << ", 邮箱: " << email << std::endl;
    }
};

// 全局向量存储所有联系人 (实际项目中通常会封装在类中)
std::vector contacts;

// 添加联系人
void addContact() {
    std::string name, phone, email;
    std::cout << "请输入姓名: ";
    std::getline(std::cin >> std::ws, name); // std::ws consumes leading whitespace
    std::cout << "请输入电话: ";
    std::getline(std::cin, phone);
    std::cout << "请输入邮箱: ";
    std::getline(std::cin, email);

    contacts.emplace_back(name, phone, email); // 使用emplace_back效率更高
    std::cout << "联系人添加成功!" << std::endl;
}

// 显示所有联系人
void displayContacts() {
    if (contacts.empty()) {
        std::cout << "通讯录为空,请先添加联系人。" << std::endl;
        return;
    }
    std::cout << "\n--- 所有联系人 ---" << std::endl;
    for (const auto& contact : contacts) {
        contact.print();
    }
    std::cout << "------------------\n" << std::endl;
}

// 搜索联系人
void searchContact() {
    if (contacts.empty()) {
        std::cout << "通讯录为空,无法搜索。" << std::endl;
        return;
    }
    std::string searchName;
    std::cout << "请输入要搜索的姓名: ";
    std::getline(std::cin >> std::ws, searchName);

    bool found = false;
    std::cout << "\n--- 搜索结果 ---" << std::endl;
    for (const auto& contact : contacts) {
        if (contact.name.find(searchName) != std::string::npos) { // 简单模糊匹配
            contact.print();
            found = true;
        }
    }
    if (!found) {
        std::cout << "未找到包含“" << searchName << "”的联系人。" << std::endl;
    }
    std::cout << "----------------\n" << std::endl;
}

// 删除联系人
void deleteContact() {
    if (contacts.empty()) {
        std::cout << "通讯录为空,无法删除。" << std::endl;
        return;
    }
    std::string deleteName;
    std::cout << "请输入要删除的联系人姓名: ";
    std::getline(std::cin >> std::ws, deleteName);

    auto it = contacts.begin();
    bool deleted = false;
    while (it != contacts.end()) {
        if (it->name == deleteName) {
            it = contacts.erase(it); // erase返回下一个元素的迭代器
            std::cout << "联系人“" << deleteName << "”已删除。" << std::endl;
            deleted = true;
            // 如果只删除第一个匹配项,可以break; 否则继续查找并删除所有匹配项
            // break;
        } else {
            ++it;
        }
    }
    if (!deleted) {
        std::cout << "未找到姓名为“" << deleteName << "”的联系人。" << std::endl;
    }
}

// 主菜单循环
int main() {
    int choice;
    do {
        std::cout << "--- 简易通讯录管理系统 ---" << 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 << "请输入您的选择: ";

        // 输入验证
        while (!(std::cin >> choice)) {
            std::cout << "无效输入,请输入数字: ";
            std::cin.clear(); // 清除错误标志
            std::cin.ignore(std::numeric_limits::max(), '\n'); // 忽略错误输入直到行尾
        }
        std::cin.ignore(std::numeric_limits::max(), '\n'); // 清除缓冲区剩余的换行符

        switch (choice) {
            case 1: addContact(); break;
            case 2: displayContacts(); break;
            case 3: searchContact(); break;
            case 4: deleteContact(); break;
            case 5: std::cout << "感谢使用,再见!" << std::endl; break;
            default: std::cout << "无效选择,请重新输入。" << std::endl; break;
        }
        std::cout << std::endl;
    } while (choice != 5);

    return 0;
}

为什么选择 std::vector 作为联系人存储容器?

在构建这样一个简易通讯录时,我个人倾向于使用 std::vector。它给我的感觉就是“够用且直观”。首先,std::vector 是一个动态数组,这意味着它能根据需要自动调整大小,我们不需要预先知道会有多少个联系人。这对于一个不断有添加和删除操作的通讯录来说,简直是太方便了。

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

BlessAI
BlessAI

Bless AI 提供五个独特的功能:每日问候、庆祝问候、祝福、祷告和名言的文本生成和图片生成。

下载

从内存角度看,std::vector 的元素是连续存储的。这一点在遍历联系人列表(比如显示所有联系人)时,性能表现会非常不错,因为数据局部性好,CPU缓存命中率高。迭代器操作也很直接,用范围for循环就能优雅地遍历所有联系人。

怎样用C++实现简易通讯录管理 vector容器存储联系人信息

当然,它并非完美无缺。在中间插入或删除元素时,std::vector 需要移动后续的所有元素,这在理论上效率并不高,时间复杂度是O(n)。但对于一个“简易”通讯录,通常联系人数量不会达到几十万上百万,几百上千条记录,这种开销几乎可以忽略不计。它的简单性和易用性,往往能弥补这一点点性能上的“劣势”。对我来说,开发效率和代码的可读性在这里更重要。

在实现联系人搜索和删除功能时,有哪些常见的挑战与优化思路?

在实际编写搜索和删除功能时,我遇到了一些值得思考的挑战。最直接的搜索方法就是线性遍历,也就是从头到尾挨个比较。对于几十个联系人,这当然没问题,速度飞快。但设想一下,如果通讯录里有几万个联系人,每次搜索都得遍历一遍,那用户体验肯定会直线下降。这就是一个典型的性能挑战。

搜索的优化思路: 如果联系人数据量变得非常大,并且搜索频率很高,我们可能需要考虑更高效的数据结构。比如,如果通讯录总是按姓名排序的,那二分查找(Binary Search)就能大大提高搜索效率,将O(n)降到O(log n)。不过,这要求每次添加或删除后都保持排序状态,这又会引入额外的排序开销。 另一种常见的思路是使用哈希表(std::unordered_map)。我们可以将联系人姓名作为键(key),联系人对象作为值(value)。这样,通过姓名查找联系人几乎是常数时间O(1)的操作。但缺点是,哈希表不保证元素的顺序,而且实现模糊搜索(比如只记得姓氏)会比较麻烦。

删除的挑战与优化: 删除操作同样有其微妙之处。std::vector::erase() 函数在删除元素后,会自动将后面的元素向前移动,以填补空缺。就像前面提到的,这个移动过程会耗费时间。如果我需要删除多个匹配的联系人,并且它们分散在向量的各个位置,那么每次erase都会导致一次数据移动,这可能会累积成不小的开销。

为了提高删除效率,一个简单的优化方法是:如果允许,可以先将要删除的元素与向量的最后一个元素交换,然后直接pop_back()。这样就避免了中间元素的移动,但缺点是会改变原有元素的相对顺序。对于通讯录这种通常不严格要求顺序的应用,这可能是一个可行的方案。 如果删除操作非常频繁,并且顺序很重要,那么std::list(双向链表)或者std::map(红黑树)可能更合适。std::list的删除是O(1)的,但随机访问是O(n)。std::map则能提供O(log n)的查找和删除。选择哪种,真的取决于具体需求和对性能的权衡。

如何让简易通讯录系统更具用户友好性和健壮性?

即使是“简易”系统,我也会尽力让它用起来更顺手,并且不容易崩溃。这关乎用户体验和程序的稳定性。

用户友好性方面: 首先是清晰的提示和菜单。用户每次操作前,都应该知道自己能做什么,以及输入什么。我的代码里就设计了一个循环菜单,每次操作结束后都会重新显示,确保用户不会迷失。 其次是友好的反馈信息。比如,添加成功了就告诉用户“联系人添加成功”,搜索不到就明确提示“未找到”。这些细节能让用户感觉程序是“活的”,而不是冷冰冰的。 再者,输入方式的考量。像姓名、电话这些包含空格的字符串,直接用std::cin >> variable可能会截断输入,所以我更倾向于用std::getline(std::cin >> std::ws, variable)来读取整行,这样用户输入“张 三”就不会只剩下“张”了。std::ws在这里的作用是消费掉之前可能留下的换行符,避免getline读到空字符串。

健壮性方面: 最常见的问题就是用户输入错误。比如,菜单选项明明是数字1-5,用户却输入了字母。如果不对这种非预期输入进行处理,程序很可能就会崩溃。我的main函数里就加入了while (!(std::cin >> choice))这样的循环来做输入验证,确保用户输入的是数字,并且在输入错误时清除错误标志和缓冲区,防止死循环。 另外,处理空列表的情况也很重要。比如,在通讯录里还没有任何联系人时,用户就尝试搜索或删除,程序不应该报错,而是应该给出友好的提示,比如“通讯录为空,无法搜索”。这都是在编写功能时需要考虑的“边界条件”或者“边缘情况”。 更进一步,像电话号码是否全是数字、邮箱格式是否正确,这些都可以加入更严格的数据校验。虽然在简易版里可能不会做得那么细致,但心里要有这个概念。通过这些细致的考量,即使是一个简单的程序,也能给人留下专业、可靠的印象。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

85

2023.09.25

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

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

254

2023.08.03

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

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

206

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

617

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

548

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

543

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

159

2025.07.29

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

36

2026.01.14

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
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号