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++ 的基础知识,提升项目思维能力。希望这篇文章能为你带来启发!如果有任何问题,欢迎留言交流~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用

文章目录 概述1. 核心思想2. 结构3. 示例代码4. 优点5. 缺点6. 适用场景7. 案例&#xff1a;模板方法模式在数据处理中的应用案例背景UML搭建抽象基类 - 数据处理的 “总指挥”子类定制 - 适配不同供应商供应商 A 的数据处理器供应商 B 的数据处理器 在业务代码中整合运用 8. 总…

计算图 Compute Graph 和自动求导 Autograd | PyTorch 深度学习实战

前一篇文章&#xff0c;Tensor 基本操作5 device 管理&#xff0c;使用 GPU 设备 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started PyTorch 计算图和 Autograd 微积分之于机器学习Computational Graphs 计算图Autograd…

C++11详解(一) -- 列表初始化,右值引用和移动语义

文章目录 1.列表初始化1.1 C98传统的{}1.2 C11中的{}1.3 C11中的std::initializer_list 2.右值引用和移动语义2.1左值和右值2.2左值引用和右值引用2.3 引用延长生命周期2.4左值和右值的参数匹配问题2.5右值引用和移动语义的使用场景2.5.1左值引用主要使用场景2.5.2移动构造和移…

Spring Boot常用注解深度解析:从入门到精通

今天&#xff0c;这篇文章带你将深入理解Spring Boot中30常用注解&#xff0c;通过代码示例和关系图&#xff0c;帮助你彻底掌握Spring核心注解的使用场景和内在联系。 一、启动类与核心注解 1.1 SpringBootApplication 组合注解&#xff1a; SpringBootApplication Confi…

生成式AI安全最佳实践 - 抵御OWASP Top 10攻击 (下)

今天小李哥将开启全新的技术分享系列&#xff0c;为大家介绍生成式AI的安全解决方案设计方法和最佳实践。近年来生成式 AI 安全市场正迅速发展。据IDC预测&#xff0c;到2025年全球 AI 安全解决方案市场规模将突破200亿美元&#xff0c;年复合增长率超过30%&#xff0c;而Gartn…

git:恢复纯版本库

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

蓝桥杯python基础算法(2-1)——排序

目录 一、排序 二、例题 P3225——宝藏排序Ⅰ 三、各种排序比较 四、例题 P3226——宝藏排序Ⅱ 一、排序 &#xff08;一&#xff09;冒泡排序 基本思想&#xff1a;比较相邻的元素&#xff0c;如果顺序错误就把它们交换过来。 &#xff08;二&#xff09;选择排序 基本思想…

python学opencv|读取图像(五十四)使用cv2.blur()函数实现图像像素均值处理

【1】引言 前序学习进程中&#xff0c;对图像的操作均基于各个像素点上的BGR值不同而展开。 对于彩色图像&#xff0c;每个像素点上的BGR值为三个整数&#xff0c;因为是三通道图像&#xff1b;对于灰度图像&#xff0c;各个像素上的BGR值是一个整数&#xff0c;因为这是单通…

Slint的学习

Slint是什么 Slint是一个跨平台的UI工具包&#xff0c;支持windows,linux,android,ios,web&#xff0c;可以用它来构建申明式UI,后端代码支持rust,c,python,nodejs等语言。 开源地址&#xff1a;https://github.com/slint-ui/slint 镜像地址&#xff1a;https://kkgithub.com/…

惰性函数【Ⅱ】《事件绑定的自我修养:从青铜到王者的进化之路》

【Ⅱ】《事件绑定的自我修养&#xff1a;从青铜到王者的进化之路》 1. 代码功能大白话&#xff08;给室友讲明白版&#xff09; // 青铜写法&#xff1a;每次都要问浏览器"你行不行&#xff1f;" function addEvent青铜版(element, type, handler) {if (window.add…

Unity飞行代码 超仿真 保姆级教程

本文使用Rigidbody控制飞机&#xff0c;基本不会穿模。 效果 飞行效果 这是一条优雅的广告 如果你也在开发飞机大战等类型的飞行游戏&#xff0c;欢迎在主页搜索博文并参考。 搜索词&#xff1a;Unity游戏(Assault空对地打击)开发。 脚本编写 首先是完整代码。 using System.Co…

基于微信小程序的私家车位共享系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

C++编程语言:抽象机制:模板(Bjarne Stroustrup)

目录 23.1 引言和概观(Introduction and Overview) 23.2 一个简单的字符串模板(A Simple String Template) 23.2.1 模板的定义(Defining a Template) 23.2.2 模板实例化(Template Instantiation) 23.3 类型检查(Type Checking) 23.3.1 类型等价(Type Equivalence) …

多线程的常用方法

getName和setName方法 注意点 setName方法最好放在线程启动之前 最好在线程启动之前修改名字&#xff0c;因为线程启动之后&#xff0c;如果执行过快的话&#xff0c;那么在调用 setName() 之前线程可能就已经结束了 MyThread t1 new MyThread("haha"); t1.setNa…

C++继承的基本意义

文章目录 一、继承的本质和原理二、重载、隐藏和覆盖三、基类与派生类的转换 一、继承的本质和原理 继承的本质&#xff1a;a. 代码的复用 b. 类和类之间的关系&#xff1a; 组合&#xff1a;a part of… 一部分的关系 继承&#xff1a;a kind of… 一种的关系 总结&#xff…

简单易懂的倒排索引详解

文章目录 简单易懂的倒排索引详解一、引言 简单易懂的倒排索引详解二、倒排索引的基本结构三、倒排索引的构建过程四、使用示例1、Mapper函数2、Reducer函数 五、总结 简单易懂的倒排索引详解 一、引言 倒排索引是一种广泛应用于搜索引擎和大数据处理中的数据结构&#xff0c;…

FinRobot:一个使用大型语言模型的金融应用开源AI代理平台

“FinRobot: An Open-Source AI Agent Platform for Financial Applications using Large Language Models” 论文地址&#xff1a;https://arxiv.org/pdf/2405.14767 Github地址&#xff1a;https://github.com/AI4Finance-Foundation/FinRobot 摘要 在金融领域与AI社区间&a…

Docker使用指南(一)——镜像相关操作详解(实战案例教学,适合小白跟学)

目录 1.镜像名的组成 2.镜像操作相关命令 镜像常用命令总结&#xff1a; 1. docker images 2. docker rmi 3. docker pull 4. docker push 5. docker save 6. docker load 7. docker tag 8. docker build 9. docker history 10. docker inspect 11. docker prune…

Qt跨屏窗口的一个Bug及解决方案

如果我们希望一个窗口覆盖用户的整个桌面&#xff0c;此时就要考虑用户有多个屏幕的场景&#xff08;此窗口要横跨多个屏幕&#xff09;&#xff0c;由于每个屏幕的分辨率和缩放比例可能是不同的&#xff0c;Qt底层在为此窗口设置缩放比例&#xff08;DevicePixelRatio&#xf…

Linux 传输层协议 UDP 和 TCP

UDP 协议 UDP 协议端格式 16 位 UDP 长度, 表示整个数据报(UDP 首部UDP 数据)的最大长度如果校验和出错, 就会直接丢弃 UDP 的特点 UDP 传输的过程类似于寄信 . 无连接: 知道对端的 IP 和端口号就直接进行传输, 不需要建立连接不可靠: 没有确认机制, 没有重传机制; 如果因…