C++实现一款功能丰富的通讯录管理系统

news2025/2/5 19:06:52

在学习编程的过程中,如何设计一个实用的项目是许多同学头疼的问题。如果你是一位正在学习C++的同学,想通过实际项目巩固知识,那么这个通讯录管理系统绝对是一个理想的练手项目。在本文中,我将详细拆解代码逻辑,帮助你理解并学习如何开发这样一个功能丰富的通讯录管理系统。


一、项目介绍

通讯录管理系统是一个简单实用的小项目,功能涵盖了联系人管理的各个方面。通过这个项目,可以学习到:

        1.C++中的结构体和指针的使用。

        2.如何将功能模块化,通过函数组织代码。

        3.交互式界面的实现。

        4.如何处理用户输入和数据校验。

二、功能展示

程序启动后,用户会看到以下操作菜单:

***************************
*****  1、添加联系人  *****
*****  2、显示联系人  *****
*****  3、删除联系人  *****
*****  4、查找联系人  *****
*****  5、修改联系人  *****
*****  6、清空联系人  *****
*****  0、退出通讯录  *****
***************************

以下是每个功能的简要说明:

        1.添加联系人:输入姓名、性别、年龄、电话、地址,添加新联系人。

        2.显示联系人:查看所有已保存的联系人信息。

        3.删除联系人:通过姓名查找并删除联系人。

        4.查找联系人:输入姓名并快速定位对应的联系人信息。

        5.修改联系人:修改已有联系人的任意信息。

        6.清空联系人:一键清空通讯录。

        7.退出程序:安全结束程序。

三、核心代码拆解

1. 通讯录的核心数据结构

在通讯录中,每个联系人由以下信息组成:姓名、性别、年龄、电话和地址。我们可以通过一个结构体来保存这些信息。

struct Person {
    string name;      // 姓名
    int sex;          // 性别:1-男,2-女
    int age;          // 年龄
    string phone;     // 电话
    string address;   // 地址
};

同时,通讯录本身是一个包含多个联系人的集合,用另一个结构体来保存这些联系人和当前联系人数量:

cpp
struct Addressbook {
    struct Person personArray[MAX]; // 容纳最多1000个联系人
    int size;                       // 实际联系人数量
};

通过这样的设计,通讯录相关的操作都可以基于Addressbook结构体进行。

2. 主界面设计与导航

程序启动后调用showMenu函数,展示选项菜单:

void showMenu() {
    cout << "***************************" << endl;
    cout << "*****  1、添加联系人  *****" << endl;
    cout << "*****  2、显示联系人  *****" << endl;
    cout << "*****  3、删除联系人  *****" << endl;
    cout << "*****  4、查找联系人  *****" << endl;
    cout << "*****  5、修改联系人  *****" << endl;
    cout << "*****  6、清空联系人  *****" << endl;
    cout << "*****  0、退出通讯录  *****" << endl;
    cout << "***************************" << endl;	
}

根据用户输入执行对应功能:

int main()
{
	int select = 0;
	
	Addressbook abs;
	abs.size = 0;
	
	while(true)
	{
		showMenu();
		
		cin >> select;
		
		switch (select) 
		{
			case 1://添加联系人
			addPerson(&abs);
			break;
			case 2://显示联系人
			showPerson(&abs);
			break;
			case 3://删除联系人
			deletePerson(&abs);
			break;
			case 4://查找联系人
			findPerson(&abs);
			break;
			case 5://修改联系人
			modifyPerson(&abs);
			break;
			case 6://清空联系人
			clearPerson(&abs);
			break;
			case 0://退出通讯录
			cout << "欢迎下次使用" << endl;
			system("pause");
			return 0;
			break;
			default:
			system("cls");
			break;
		}
	}
	
	system("pause");
	return 0;
	
}

3. 添加联系人

添加联系人是程序的核心功能之一,需要进行多次用户输入并校验数据:

void addPerson(Addressbook *abs) {
    if (abs->size == MAX) {
        cout << "通讯录已满,无法添加!" << endl;
        return;
    }

    // 姓名
    string tempName;
    cout << "请输入姓名: " << endl;
    cin >> tempName;
    abs->personArray[abs->size].name = tempName;

    // 性别
    int tempSex;
    cout << "请输入性别:1-男,2-女" << endl;
    while (true) {
        cin >> tempSex;
        if (tempSex == 1 || tempSex == 2) {
            abs->personArray[abs->size].sex = tempSex;
            break;
        }
        cout << "输入有误,请重新输入" << endl;	
    }

    // 年龄
    cout << "请输入年龄:" << endl;
    int tempAge;
    while (true) {
        cin >> tempAge;
        if (tempAge >= 0 && tempAge <= 150) {
            abs->personArray[abs->size].age = tempAge;
            break;
        }
        cout << "输入有误,请重新输入" << endl;
    }

    // 电话
    cout << "请输入联系电话:" << endl;
    string tempPhone;
    while (true) {
        cin >> tempPhone;
        if (tempPhone.length() == 11) {
            abs->personArray[abs->size].phone = tempPhone;
            break;
        }
        cout << "输入有误,请重新输入" << endl;
    }

    // 地址
    string tempAddress;
    cout << "请输入地址:" << endl;
    cin >> tempAddress;
    abs->personArray[abs->size].address = tempAddress;

    // 更新通讯录的人数
    abs->size++;
    cout << "添加成功" << endl;

    system("pause");
    system("cls");
}

编写代码的注意点:

        1.边界条件检查:如性别只能是1或2,年龄限制在0到150之间了,手机号必须是11位。

        2.动态更新通讯录:每次新增联系人后,abs->size++会加1。

4. 删除联系人

删除联系人需要先通过姓名查找目标联系人,然后从数组中移除该联系人:

int isExist(Addressbook *abs, string tempName) {
    for (int i = 0; i < abs->size; i++) {
        if (abs->personArray[i].name == tempName) {
            return i; // 返回联系人索引
        }
    }
    return -1; // 未找到
}

void deletePerson(Addressbook *abs) {
    cout << "请输入您要删除的联系人: " << endl;
    string tempName;
    cin >> tempName;

    int flag = isExist(abs, tempName);
    if (flag != -1) {
        for (int i = flag; i < abs->size - 1; i++) {
            abs->personArray[i] = abs->personArray[i + 1];
        }
        abs->size--; // 数组大小减少
        cout << "删除成功" << endl;
    } else {
        cout << "查无此人" << endl;
    }
}

功能说明

  1. 提示用户输入需要删除的联系人姓名。
  2. 调用isExist函数,确认该联系人是否存在。
  3. 如果存在,通过数据覆盖的方式删除该联系人。如果不存在,提示用户 "查无此人"。
  4. 减小通讯录的实际大小,确保删除后的数据一致性

5.显示联系人

显示联系人是程序的一个重要基础功能,通过遍历通讯录结构体,将每个联系人的信息打印到屏幕上:

void showPerson(Addressbook *abs) {
    if (abs->size == 0) {
        cout << "当前通讯录为空" << endl;
    } else {
        for (int i = 0; i < abs->size; i++) {
            cout << "姓名: " << abs->personArray[i].name << "\t";
            cout << "性别: " << (abs->personArray[i].sex == 1 ? "男" : "女") << "\t";
            cout << "年龄: " << abs->personArray[i].age << "\t";
            cout << "电话: " << abs->personArray[i].phone << "\t";
            cout << "住址: " << abs->personArray[i].address << endl;
        }
    }
    
    // 暂停窗口并清屏
    system("pause");
    system("cls");
}

功能说明:

        1.如果通讯录为空,直接提示用户。

        2.遍历联系人列表,逐条打印每个联系人的信息,包括姓名、性别、年龄、电话和地址。

6.查找联系人

通过输入姓名快速定位指定的联系人,并显示其详细信息:

void findPerson(Addressbook *abs) {
    cout << "请输入您要查找的联系人:" << endl;
    string tempName;
    cin >> tempName;

    int flag = isExist(abs, tempName);
    if (flag != -1) {
        cout << "姓名: " << abs->personArray[flag].name << "\t";
        cout << "性别: " << (abs->personArray[flag].sex == 1 ? "男" : "女") << "\t";
        cout << "年龄: " << abs->personArray[flag].age << "\t";
        cout << "电话: " << abs->personArray[flag].phone << "\t";
        cout << "住址: " << abs->personArray[flag].address << endl;
    } else {
        cout << "查无此人" << endl;
    }

    // 暂停窗口并清屏
    system("pause");
    system("cls");
}

辅助函数:判断联系人是否存在

int isExist(Addressbook *abs, string tempName) {
    for (int i = 0; i < abs->size; i++) {
        if (abs->personArray[i].name == tempName) {
            return i; // 返回联系人索引
        }
    }
    return -1; // 未找到
}

功能说明

        1.用户输入姓名后调用isExist函数检查联系人是否存在。

        2.如果找到,打印该联系人的详细信息。

        3.如果未找到,提示 "查无此人"。

7.清空联系人

清空联系人功能将通讯录中现有的所有联系人清空,并重置联系人数量为0:

void clearPerson(Addressbook *abs) {
    cout << "您是否确认要清空所有联系人?" << endl;
    cout << "1 --- 确认" << endl;
    cout << "0 --- 退出" << endl;

    int flag = 0;
    cin >> flag;
    if (flag == 1) {
        abs->size = 0; // 重置通讯录大小
        cout << "联系人已全部清空" << endl;
    }

    // 暂停窗口并清屏
    system("pause");
    system("cls");
}

功能说明

        1.用户需要确认是否清空联系人。

        2.如果用户选择 "确认",将联系人数量置为 0。

        3.如果用户选择 "退出",返回菜单界面,不做任何修改。

四、完整代码与下载链接

主要核心代码已经在上文展示, GItHub源码链接:通讯录管理系统。

通过这个项目,可以巩固 C++ 的基础知识,提升项目思维能力。希望这篇文章能为你带来启发!如果有任何问题,欢迎留言交流~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2293439.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【力扣】53.最大子数组和

AC截图 题目 思路 这道题主要考虑的就是要排除负数带来的负面影响。如果遍历数组&#xff0c;那么应该有如下关系式&#xff1a; currentAns max(prenums[i],nums[i]) pre是之前记录的最大和&#xff0c;如果prenums[i]小于nums[i]&#xff0c;就要考虑舍弃pre&#xff0c;从…

基于Spring Security 6的OAuth2 系列之七 - 授权服务器--自定义数据库客户端信息

之所以想写这一系列&#xff0c;是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器&#xff0c;但当时基于spring-boot 2.3.x&#xff0c;其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0&#xff0c;结果一看Spring Security也升级…

vim-plug的自动安装与基本使用介绍

vim-plug介绍 Vim-plug 是一个轻量级的 Vim 插件管理器&#xff0c;它允许你轻松地管理 Vim 插件的安装、更新和卸载。相较于其他插件管理器&#xff0c;vim-plug 的优点是简单易用&#xff0c;速度较快&#xff0c;而且支持懒加载插件&#xff08;即按需加载&#xff09; 自动…

Deep Crossing:深度交叉网络在推荐系统中的应用

实验和完整代码 完整代码实现和jupyter运行&#xff1a;https://github.com/Myolive-Lin/RecSys--deep-learning-recommendation-system/tree/main 引言 在机器学习和深度学习领域&#xff0c;特征工程一直是一个关键步骤&#xff0c;尤其是对于大规模的推荐系统和广告点击率预…

想品客老师的第十天:类

类是一个优化js面向对象的工具 类的声明 //1、class User{}console.log(typeof User)//function//2、let Hdclass{}//其实跟1差不多class Stu{show(){}//注意这里不用加逗号&#xff0c;对象才加逗号get(){console.log(后盾人)}}let hdnew Stu()hd.get()//后盾人 类的原理 类…

MyBatis-Plus速成指南:条件构造器和常用接口

Wrapper 介绍 Wrapper&#xff1a;条件构造抽象类&#xff0c;最顶端父类 AbstractWrapper&#xff1a;用于查询条件封装&#xff0c;生成 SQL 的 where 条件QueryWrapper&#xff1a;查询条件封装UpdateWrapper&#xff1a;Update 条件封装AbstractLambdaWrapper&#xff1a;使…

(脚本学习)BUU18 [CISCN2019 华北赛区 Day2 Web1]Hack World1

自用 题目 考虑是不是布尔盲注&#xff0c;如何测试&#xff1a;用"1^1^11 1^0^10&#xff0c;就像是真真真等于真&#xff0c;真假真等于假"这个测试 SQL布尔盲注脚本1 import requestsurl "http://8e4a9bf2-c055-4680-91fd-5b969ebc209e.node5.buuoj.cn…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.25 多线程并行:GIL绕过与真正并发

2.25 多线程并行&#xff1a;GIL绕过与真正并发 目录 #mermaid-svg-JO4lsTIyjOweVkos {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-JO4lsTIyjOweVkos .error-icon{fill:#552222;}#mermaid-svg-JO4lsTIyjOweVkos …

Java 大视界 -- Java 大数据在智能医疗影像诊断中的应用(72)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也期待你毫无保留地分享独特见解,愿我们于此携手成长,共赴新程!💖 一、…

【Leetcode刷题记录】1456. 定长子串中元音的最大数目---定长滑动窗口即解题思路总结

1456. 定长子串中元音的最大数目 给你字符串 s 和整数 k 。请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。 英文中的 元音字母 为&#xff08;a, e, i, o, u&#xff09;。 这道题的暴力求解的思路是通过遍历字符串 s 的每一个长度为 k 的子串&#xf…

upload-labs安装与配置

前言 作者进行upload-labs靶场练习时&#xff0c;在环境上出了很多问题&#xff0c;吃了很多苦头&#xff0c;甚至改了很多配置也没有成功。 upload-labs很多操作都是旧时代的产物了&#xff0c;配置普遍都比较老&#xff0c;比如PHP版本用5.2.17&#xff08;还有中间件等&am…

从Transformer到世界模型:AGI核心架构演进

文章目录 引言:架构革命推动AGI进化一、Transformer:重新定义序列建模1.1 注意力机制的革命性突破1.2 从NLP到跨模态演进1.3 规模扩展的黄金定律二、通向世界模型的关键跃迁2.1 从语言模型到认知架构2.2 世界模型的核心特征2.3 混合架构的突破三、构建世界模型的技术路径3.1 …

每日一博 - 三高系统架构设计:高性能、高并发、高可用性解析

文章目录 引言一、高性能篇1.1 高性能的核心意义1.2 影响系统性能的因素1.3 高性能优化方法论1.3.1 读优化&#xff1a;缓存与数据库的结合1.3.2 写优化&#xff1a;异步化处理 1.4 高性能优化实践1.4.1 本地缓存 vs 分布式缓存1.4.2 数据库优化 二、高并发篇2.1 高并发的核心意…

【工欲善其事】利用 DeepSeek 实现复杂 Git 操作:从原项目剥离出子版本树并同步到新的代码库中

文章目录 利用 DeepSeek 实现复杂 Git 操作1 背景介绍2 需求描述3 思路分析4 实现过程4.1 第一次需求确认4.2 第二次需求确认4.3 第三次需求确认4.4 V3 模型&#xff1a;中间结果的处理4.5 方案验证&#xff0c;首战告捷 5 总结复盘 利用 DeepSeek 实现复杂 Git 操作 1 背景介绍…

【C++】线程池实现

目录 一、线程池简介线程池的核心组件实现步骤 二、C11实现线程池源码 三、线程池源码解析1. 成员变量2. 构造函数2.1 线程初始化2.2 工作线程逻辑 3. 任务提交(enqueue方法)3.1 方法签名3.2 任务封装3.3 任务入队 4. 析构函数4.1 停机控制 5. 关键技术点解析5.1 完美转发实现5…

数据结构实战之线性表(三)

目录 1.顺序表释放 2.顺序表增加空间 3.合并顺序表 4.线性表之链表实现 1.项目结构以及初始代码 2.初始化链表(不带头结点) 3.链表尾部插入数据并显示 4.链表头部插入数据 5.初始化链表&#xff08;带头结点&#xff09; 6.带头结点的链表头部插入数据并显示 7.带头结…

【python】python基于机器学习与数据分析的手机特性关联与分类预测(源码+数据集)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 python基于机器学习与数据分析的手机特性关联与分类…

ZOJ 1007 Numerical Summation of a Series

原题目链接 生成该系列值的表格 对于x 的 2001 个值&#xff0c;x 0.000、0.001、0.002、…、2.000。表中的所有条目的绝对误差必须小于 0.5e-12&#xff08;精度为 12 位&#xff09;。此问题基于 Hamming (1962) 的一个问题&#xff0c;当时的大型机按今天的微型计算机标准来…

全面解析文件上传下载删除漏洞:风险与应对

在数字化转型的时代&#xff0c;文件上传、下载与删除功能已经成为各类应用程序的标准配置&#xff0c;从日常办公使用的协同平台&#xff0c;到云端存储服务&#xff0c;再到社交网络应用&#xff0c;这些功能在给用户带来便捷体验、显著提升工作效率的同时&#xff0c;也隐藏…

【C语言深入探索】结构体详解(二):使用场景

目录 一、复杂数据的表示 二、数据的封装 三、多态的模拟 四、回调函数的实现 五、多线程编程 六、通信协议的实现和文件操作 6.1. 使用结构体实现简单通信协议 6.2. 使用结构体进行文件操作 七、图形界面编程 结构体在C语言中具有广泛的应用场景&#xff0c;以下是一…