当前位置: 首页 > article >正文

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

在学习编程的过程中,如何设计一个实用的项目是许多同学头疼的问题。如果你是一位正在学习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++ 的基础知识,提升项目思维能力。希望这篇文章能为你带来启发!如果有任何问题,欢迎留言交流~

相关文章:

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

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

Selenium 使用指南:从入门到精通

Selenium 使用指南&#xff1a;从入门到精通 Selenium 是一个用于自动化 Web 浏览器操作的强大工具&#xff0c;广泛应用于自动化测试和 Web 数据爬取中。本文将带你从入门到精通地掌握 Selenium&#xff0c;涵盖其基本操作、常用用法以及一个完整的图片爬取示例。 1. 环境配…...

【力扣】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()//后盾人 类的原理 类…...

4 前端前置技术(上):AJAX技术(前端发送请求)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 前言...

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

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

LeetCode 0922.按奇偶排序数组 II:O(1)空间复杂度-一次遍历双指针

【LetMeFly】922.按奇偶排序数组 II&#xff1a;O(1)空间复杂度-一次遍历双指针 力扣题目链接&#xff1a;https://leetcode.cn/problems/sort-array-by-parity-ii/ 给定一个非负整数数组 nums&#xff0c; nums 中一半整数是 奇数 &#xff0c;一半整数是 偶数 。 对数组进…...

windows环境下如何在PyCharm中安装软件包

windows环境下如何在pyCharm中安装wxPython软件包 在windows环境中&#xff0c;安装软件包可以使用 终端 的方式&#xff0c;在IDE下方的终端中执行pip install wxPython进行安装&#xff0c;安装完毕之后&#xff0c;使用pip show wxPython检查也符合预期。 但是在代码文件中导…...

(脚本学习)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 …...

pytorch深度Q网络

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 DQN 引入了深度神经网络来近似Q函数&#xff0c;解决了传统Q-learning在处理高维状态空间时的瓶颈&#xff0c;尤其是在像 Atari 游戏这样的复杂环境中。DQN的核心思想是使用神经网络 Q(s,a;θ)Q(s, a; \theta)Q(s,…...

C++ 实现Arp断网

此程序由AI生成&#xff0c;测试过了&#xff0c;可以使用 但是&#xff0c;貌似全部都会断网 #include <pcap.h> #include <WinSock2.h> #include <iostream> #include <vector> #include <string> #include <sstream> #include <iom…...

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

文章目录 引言一、高性能篇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 高并发的核心意…...

Vue2 项目中使用 Swiper

Swiper 是一个功能强大的轮播图库&#xff0c;支持触摸滑动、分页器、导航按钮等功能。本文将详细介绍如何在Vue2项目中集成Swiper 5&#xff0c;并通过watch和nextTick确保Swiper在数据加载完成后正确初始化。 1. 安装Swiper 5 首先&#xff0c;我们需要通过npm或yarn安装Sw…...

【工欲善其事】利用 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 背景介绍…...

Kafka的安装及相关操作命令

文章目录 前言一、安装kafka1. 下载kafka2. 解压kafka3. 配置环境变量 二、kafka相关命令1. 启动zk2. 启动Kafka Broker3. 创建主题4. 列出所有主题5. 查看主题详情6. 删除主题7. 启动控制台生产者8. 启动控制台消费者9. 验证结果10. 其他 前言 kafka_2.11-0.10.2.1&#xff0…...

【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.带头结…...

C#方法作用

C#方法 方法的定义与调用 首先我们要知道什么是方法,为什么要去使用方法? 方法就是把一些相关的语句组织在一起,用来执行的语句块 每一个C#程序至少有一个带有Main方法 static void Main(string[] args){ //方法的定义,一般情况下,写在一个类中// 格式: 访问修饰符 返回值…...

【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;当时的大型机按今天的微型计算机标准来…...

DeepSeek-R1:开源机器人智能控制系统的革命性突破

目录 引言 一、DeepSeek-R1 的概述 1.1 什么是 DeepSeek-R1&#xff1f; 1.2 DeepSeek-R1 的定位 二、DeepSeek-R1 的核心特性 2.1 实时控制能力 2.2 多传感器融合 2.3 路径规划与导航 2.4 人工智能集成 2.5 开源与模块化设计 2.6 跨平台支持 三、DeepSeek-R1 的技术…...

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

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