IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++实现通讯录系统程序(小白文) -> 正文阅读

[C++知识库]C++实现通讯录系统程序(小白文)

前言

最近跟着b站的c++视频做了一个通讯录管理系统的程序,本文会简单分析这种程序代码的结构、设计思路以及涉及其中的一些c++语言知识和用法。
在此附上相关视频链接:https://www.bilibili.com/video/BV1et411b73Z?p=83&spm_id_from=pageDriver
如若涉及侵权,请告知作者删改

一、程序设计思路

先来看看这个程序的需要的功能
在这里插入图片描述
从这张图片我们可以看到,这样的一个通讯录管理系统的功能上就有7个选项,除开最后的“退出通讯录”,共有6个功能。从功能导向的思路来看,我们至少需要6个相应的函数去实现。
除此之外,我们还需要显示该菜单,除了0选项之外,每个功能使用后还可再次使用,或者选择其他功能,而菜单提供的功能又这么多,说明我们在main函数中需要循环结构和分支选择结构。

二、代码结构(附相关源码)

1、菜单栏显示

要显示上面的菜单,而且会出现多次使用该菜单的情况,不妨将其定义成函数。(当然,宏定义也是可以,读者不妨可以试试)

// 封装函数显示界面 void 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;
}

2、功能选择

前面提到了这一块的思路:循环+分支选择

// 在main函数中调用函数
int main()
{
	// 声明选择变量
	int select = 0;

	// 创建通讯录结构体
	Address_List adl;

	// 初始化通讯录人数
	adl.m_size = 0;


	while (1)
	{
		// 菜单调用
		showMenu();

		// 输入选择
		cin >> select;

		// switch 多分支结构
		switch (select)
		{
		case 1:	// 1、添加联系人
			addPerson(&adl);
			break;
		case 2:	// 2、显示联系人
			showPerson(&adl);
			break;
		case 3:	// 3、删除联系人
		//{
		//	/*string name;
		//	cout << "请输入删除联系人姓名: " << endl;
		//	cin >> name;*/
		//	/*if (isExist(&adl, name) != -1)
		//	{
		//		cout << "找到联系人" << endl;
		//	}
		//	else
		//	{
		//		cout << "查无此人" << endl;
		//	}*/
		//}
			deletePerson(&adl);
			break;
		case 4: // 4、查找联系人
			findPerson(&adl);
			break;
		case 5: // 5、修改联系人
			modifyPerson(&adl);
			break;
		case 6: // 6、清空联系人
			cleanPerson(&adl);
			break;
		case 0: // 0、推出通讯录
			cout << "欢迎下次使用" << endl;
			system("pause");
			return 0;
		default:
			break;
		}
	}

	system("pause");

	return 0;
}

其中的一些自定义的结构体变量,在此有相关代码

// 定义联系人结构体
struct Person
{
	// 姓名
	string m_name;
	// 性别  1表示男, 2 表示女
	int m_gender;
	// 年龄
	int m_age;
	// 手机号码
	string m_phone_number;
	// 地址
	string m_address;
};

// 定义通讯录结构体
struct Address_List
{
	// 通讯录中保存的联系人数组
	Person personArr[MAX];
	
	// 通讯录中记录当前联系人人数
	int m_size;
};

结构体变量有“联系人”结构体和“通讯录”结构体。前者用来记录联系人的信息,后者用于存储联系人结构体。

3、添加联系人

联系人的添加涉及到了数据的输入,存储。
而存储是有限的,对通讯录数组的最大容量有限制。因此在添加联系人时要先判断通讯录是否满了。

// 1、添加联系人
void addPerson(Address_List* adl)
{
	// 判断通讯录是否已经满了
	if (adl->m_size == MAX)
	{
		cout << "通讯录已满,无法添加!" << endl;
	}
	// 添加
	else
	{
		// 姓名
		string name;
		cout << "请输入姓名: " << endl;
		cin >> name;
		adl->personArr[adl->m_size].m_name = name;

		// 性别
		int gender;
		cout << "请输入性别: " << endl;
		cout << "1——男" << endl;
		cout << "2——女" << endl;
		while (1)
		{
			cin >> gender;
			if (gender == 1 || gender == 2)
			{
				adl->personArr[adl->m_size].m_gender = gender;
				break;
			}
			cout << "错误输入,请重新输入!" << endl;
		}

		// 年龄
		int age;
		cout << "请输入年龄: " << endl;
		while (1)
		{
			cin >> age;
			if (age >= 0 && age <= 150)
			{
				adl->personArr[adl->m_size].m_age = age;
				break;
			}
			cout << "错误输入,请重新输入!" << endl;
		}

		// 手机号码
		string phonenum;
		cout << "请输入手机号码: " << endl;
		while (1)
		{
			cin >> phonenum;
			// 声明变量,用于检验手机号码是否输入正确
			int b = 0;
			int len = phonenum.length();
			for (int i = 0; i < len; i++)
			{
				if (phonenum[i] >= 48 && phonenum[i] <= 57)
				{
					continue;
				}
				b = 1;
				break;
			}
			if (b)
			{
				cout << "手机号码输入错误,请重新输入: " << endl;
			}
			else
			{
				adl->personArr[adl->m_size].m_phone_number = phonenum;
				break;
			}
		}

		// 地址
		string address;
		cout << "请输入联系人地址: " << endl;
		cin >> address;
		adl->personArr[adl->m_size].m_address = address;

		// 提示输入成功
		cout << "添加成功!" << endl;

		// 通讯录联系人数量增加(更新)
		adl->m_size++;

		system("pause");	// 请按任意键继续
		system("cls");		// 清屏操作
	}
}

这其中在输入上有一些考量与限制,比如性别,手机号码。

4、显示联系人

思路:先判断通讯录是否为空,不空才输出联系人信息。

// 2、显示联系人
void showPerson(Address_List* adl)
{
	// 判断通讯录是否为空 如果为空,则输出提示信息,否则,输出联系人信息
	if (adl->m_size == 0)
	{
		cout << "当前通讯录记录为空" << endl;
	}
	else
	{
		for (int i = 0; i < adl->m_size; i++)
		{
			cout << "姓名: " << adl->personArr[i].m_name << "\t"
				<< "性别: " << (adl->personArr[i].m_gender == 1 ? "男" : "女") << "\t"
				<< "年龄: " << adl->personArr[i].m_age << "\t"
				<< "手机号码: " << adl->personArr[i].m_phone_number << "\t"
				<< "地址: " << adl->personArr[i].m_address << endl;
		}
	}
	system("pause");
	system("cls");
}

5、删除联系人

思路类似,需要先判断联系人是否在通讯录中。
然后,对删除操作的思路其实就是做循环让后面的联系人信息覆盖要删除的信息,这种思路在作者的上一篇blog即编程题总结中的第一题数组原地去重的思路类似。
删除后,会更新通讯录中联系人人数。

// 3、删除联系人
// 检测联系人是否存在, 如果存在返回联系人在数组中的索引,不存在返回-1
int isExist(Address_List* adl, string name)
{
	// 遍历通讯录
	for (int i = 0; i < adl->m_size; i++)
	{
		// 找到了
		if (adl->personArr[i].m_name == name)
		{
			return i;
		}
	}
	// 没找到
	return -1;
}
// 删除函数
void deletePerson(Address_List* adl)
{
	cout << "请输入你要删除的联系人: " << endl;

	string name;
	cin >> name;
	int ret = isExist(adl, name);
	if (ret == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		for (int i = ret; i < adl->m_size; i++)
		{
			adl->personArr[i] = adl->personArr[i + 1];
		}
		adl->m_size--;
		cout << "删除成功!" << endl;
	}
	system("pause");
	system("cls");
}

6、查找联系人

与删除类似,判断联系人是否在通讯录,同时利用判断函数返回的联系人在通讯录数组的索引。

// 4、查找联系人
void findPerson(Address_List* adl)
{
	cout << "请输入你要查找的联系人: " << endl;
	string name;
	cin >> name;
	int ret = isExist(adl, name);
	if (ret != -1)
	{
		cout << "姓名: " << adl->personArr[ret].m_name << "\t"
			<< "性别: " << (adl->personArr[ret].m_gender == 1 ? "男" : "女") << "\t"
			<< "年龄: " << adl->personArr[ret].m_age << "\t"
			<< "手机号码: " << adl->personArr[ret].m_phone_number << "\t"
			<< "地址: " << adl->personArr[ret].m_address << endl;
	}
	else
	{
		cout << "查无此人!" << endl;
	}
	system("pause");
	system("cls");
}

7、修改联系人

思路类似,同时由于涉及到信息的输入,所以也要考虑前面的添加联系人需要考虑的因素。

// 5、修改联系人
void modifyPerson(Address_List* adl)
{
	cout << "请输入你要修改的联系人" << endl;
	string name;
	cin >> name;
	int ret = isExist(adl, name);
	if (ret == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		// 姓名
		cout << "请输入姓名: " << endl;
		cin >> name;
		adl->personArr[ret].m_name = name;

		// 性别
		cout << "请输入性别: " << endl;
		cout << "1——男" << endl
			<< "2——女" << endl;
		int gender;
		while (1)
		{
			cin >> gender;
			if (gender == 1 || gender == 2)
			{
				adl->personArr[ret].m_gender = gender;
				break;
			}
			cout << "性别输入错误,请重新输入" << endl;
		}

		// 年龄
		cout << "请输入年龄: " << endl;
		int age;
		while (1)
		{
			cin >> age;
			if (age >= 0 && age <= 150)
			{
				adl->personArr[ret].m_age = age;
				break;
			}
			cout << "年龄输入错误,请重新输入" << endl;
		}

		// 手机号码
		cout << "请输入联系人号码: " << endl;
		string phonenum;
		while (1)
		{
			cin >> phonenum;
			// 声明变量,用于检验手机号码是否输入正确
			int b = 0;
			int len = phonenum.length();
			for (int i = 0; i < len; i++)
			{
				if (phonenum[i] >= 48 && phonenum[i] <= 57)
				{
					continue;
				}
				b = 1;
				break;
			}
			if (b)
			{
				cout << "手机号码输入错误,请重新输入: " << endl;
			}
			else
			{
				adl->personArr[adl->m_size].m_phone_number = phonenum;
				break;
			}
		}

		// 地址
		cout << "请输入地址: " << endl;
		string address;
		cin >> address;
		adl->personArr[ret].m_address = address;

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

8、清空联系人

就是清空通讯录,前面提到的用来记录的通讯录中联系人数量的变量此时做赋值为0的操作,而不是真的一个个去把这些信息去除掉,思路和删除联系人类似。

// 6、清空联系人
void cleanPerson(Address_List* adl)
{
	cout << "是否需要清空通讯录" << endl
		<< "1——是\t2——否" << endl;
	int n = 0;
	while (true)
	{
		cin >> n;
		if (n == 1)
		{
			adl->m_size = 0;
			cout << "通讯录已清空" << endl;
			break;
		}
		else if (n == 2)
		{
			break;
		}
		else
		{
			cout << "错误输入,请重新输入" << endl;
		}
	}
	system("pause");
	system("cls");
}

二、小知识

1、数据结构数组和数据结构的嵌套
在这里插入图片描述
如图,这种在一个数据结构的定义中提到另一个数据结构就是数据结构的嵌套,同时personArr也是一种数据结构数组。
2、指针使用
在这里插入图片描述
在本文中的大量代码,尤其是函数的参数都使用了数据结构指针,为什么不适用值传递,而是选择指针传递呢?
原因有二:其一,指针传递可以直接对通讯录联系人等信息的修改;其二,当通讯录中联系人太多的时候会导致函数在调用的时候使用内存太大。这无疑会导致函数的栈帧空间过大,会使得这个程序的空间复杂度过大。而指针的好处在于,c++对于指针,其内存被定义为4个字节。无论这个指针的类型是什么。在函数调用,内存可以有极大的节省。

3、清屏操作

在这里插入图片描述

system(“pause”) 用于任意键继续
system(“cls”) 用于清屏操作
使用清屏主要是因为,在每次使用一次功能菜单后的信息显示过多,而且当使用次数过多时会显得很不美观。清屏配合循环结构在显示上会很棒。

三、程序源码

#include <iostream>
#include<string>
using namespace std;

// 定义通讯录容量
#define MAX 1000

// 定义联系人结构体
struct Person
{
	// 姓名
	string m_name;
	// 性别  1表示男, 2 表示女
	int m_gender;
	// 年龄
	int m_age;
	// 手机号码
	string m_phone_number;
	// 地址
	string m_address;
};

// 定义通讯录结构体
struct Address_List
{
	// 通讯录中保存的联系人数组
	Person personArr[MAX];
	
	// 通讯录中记录当前联系人人数
	int m_size;
};

// 封装函数显示界面 void 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;
}

// 1、添加联系人
void addPerson(Address_List* adl)
{
	// 判断通讯录是否已经满了
	if (adl->m_size == MAX)
	{
		cout << "通讯录已满,无法添加!" << endl;
	}
	// 添加
	else
	{
		// 姓名
		string name;
		cout << "请输入姓名: " << endl;
		cin >> name;
		adl->personArr[adl->m_size].m_name = name;

		// 性别
		int gender;
		cout << "请输入性别: " << endl;
		cout << "1——男" << endl;
		cout << "2——女" << endl;
		while (1)
		{
			cin >> gender;
			if (gender == 1 || gender == 2)
			{
				adl->personArr[adl->m_size].m_gender = gender;
				break;
			}
			cout << "错误输入,请重新输入!" << endl;
		}

		// 年龄
		int age;
		cout << "请输入年龄: " << endl;
		while (1)
		{
			cin >> age;
			if (age >= 0 && age <= 150)
			{
				adl->personArr[adl->m_size].m_age = age;
				break;
			}
			cout << "错误输入,请重新输入!" << endl;
		}

		// 手机号码
		string phonenum;
		cout << "请输入手机号码: " << endl;
		while (1)
		{
			cin >> phonenum;
			// 声明变量,用于检验手机号码是否输入正确
			int b = 0;
			int len = phonenum.length();
			for (int i = 0; i < len; i++)
			{
				if (phonenum[i] >= 48 && phonenum[i] <= 57)
				{
					continue;
				}
				b = 1;
				break;
			}
			if (b)
			{
				cout << "手机号码输入错误,请重新输入: " << endl;
			}
			else
			{
				adl->personArr[adl->m_size].m_phone_number = phonenum;
				break;
			}
		}

		// 地址
		string address;
		cout << "请输入联系人地址: " << endl;
		cin >> address;
		adl->personArr[adl->m_size].m_address = address;

		// 提示输入成功
		cout << "添加成功!" << endl;

		// 通讯录联系人数量增加(更新)
		adl->m_size++;

		system("pause");	// 请按任意键继续
		system("cls");		// 清屏操作
	}
}

// 2、显示联系人
void showPerson(Address_List* adl)
{
	// 判断通讯录是否为空 如果为空,则输出提示信息,否则,输出联系人信息
	if (adl->m_size == 0)
	{
		cout << "当前通讯录记录为空" << endl;
	}
	else
	{
		for (int i = 0; i < adl->m_size; i++)
		{
			cout << "姓名: " << adl->personArr[i].m_name << "\t"
				<< "性别: " << (adl->personArr[i].m_gender == 1 ? "男" : "女") << "\t"
				<< "年龄: " << adl->personArr[i].m_age << "\t"
				<< "手机号码: " << adl->personArr[i].m_phone_number << "\t"
				<< "地址: " << adl->personArr[i].m_address << endl;
		}
	}
	system("pause");
	system("cls");
}

// 3、删除联系人
// 检测联系人是否存在, 如果存在返回联系人在数组中的索引,不存在返回-1
int isExist(Address_List* adl, string name)
{
	// 遍历通讯录
	for (int i = 0; i < adl->m_size; i++)
	{
		// 找到了
		if (adl->personArr[i].m_name == name)
		{
			return i;
		}
	}
	// 没找到
	return -1;
}
// 删除函数
void deletePerson(Address_List* adl)
{
	cout << "请输入你要删除的联系人: " << endl;

	string name;
	cin >> name;
	int ret = isExist(adl, name);
	if (ret == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		for (int i = ret; i < adl->m_size; i++)
		{
			adl->personArr[i] = adl->personArr[i + 1];
		}
		adl->m_size--;
		cout << "删除成功!" << endl;
	}
	system("pause");
	system("cls");
}

// 4、查找联系人
void findPerson(Address_List* adl)
{
	cout << "请输入你要查找的联系人: " << endl;
	string name;
	cin >> name;
	int ret = isExist(adl, name);
	if (ret != -1)
	{
		cout << "姓名: " << adl->personArr[ret].m_name << "\t"
			<< "性别: " << (adl->personArr[ret].m_gender == 1 ? "男" : "女") << "\t"
			<< "年龄: " << adl->personArr[ret].m_age << "\t"
			<< "手机号码: " << adl->personArr[ret].m_phone_number << "\t"
			<< "地址: " << adl->personArr[ret].m_address << endl;
	}
	else
	{
		cout << "查无此人!" << endl;
	}
	system("pause");
	system("cls");
}
// 5、修改联系人
void modifyPerson(Address_List* adl)
{
	cout << "请输入你要修改的联系人" << endl;
	string name;
	cin >> name;
	int ret = isExist(adl, name);
	if (ret == -1)
	{
		cout << "查无此人" << endl;
	}
	else
	{
		// 姓名
		cout << "请输入姓名: " << endl;
		cin >> name;
		adl->personArr[ret].m_name = name;

		// 性别
		cout << "请输入性别: " << endl;
		cout << "1——男" << endl
			<< "2——女" << endl;
		int gender;
		while (1)
		{
			cin >> gender;
			if (gender == 1 || gender == 2)
			{
				adl->personArr[ret].m_gender = gender;
				break;
			}
			cout << "性别输入错误,请重新输入" << endl;
		}

		// 年龄
		cout << "请输入年龄: " << endl;
		int age;
		while (1)
		{
			cin >> age;
			if (age >= 0 && age <= 150)
			{
				adl->personArr[ret].m_age = age;
				break;
			}
			cout << "年龄输入错误,请重新输入" << endl;
		}

		// 手机号码
		cout << "请输入联系人号码: " << endl;
		string phonenum;
		while (1)
		{
			cin >> phonenum;
			// 声明变量,用于检验手机号码是否输入正确
			int b = 0;
			int len = phonenum.length();
			for (int i = 0; i < len; i++)
			{
				if (phonenum[i] >= 48 && phonenum[i] <= 57)
				{
					continue;
				}
				b = 1;
				break;
			}
			if (b)
			{
				cout << "手机号码输入错误,请重新输入: " << endl;
			}
			else
			{
				adl->personArr[adl->m_size].m_phone_number = phonenum;
				break;
			}
		}

		// 地址
		cout << "请输入地址: " << endl;
		string address;
		cin >> address;
		adl->personArr[ret].m_address = address;

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

// 6、清空联系人
void cleanPerson(Address_List* adl)
{
	cout << "是否需要清空通讯录" << endl
		<< "1——是\t2——否" << endl;
	int n = 0;
	while (true)
	{
		cin >> n;
		if (n == 1)
		{
			adl->m_size = 0;
			cout << "通讯录已清空" << endl;
			break;
		}
		else if (n == 2)
		{
			break;
		}
		else
		{
			cout << "错误输入,请重新输入" << endl;
		}
	}
	system("pause");
	system("cls");
}

// 在main函数中调用函数
int main()
{
	// 声明选择变量
	int select = 0;

	// 创建通讯录结构体
	Address_List adl;

	// 初始化通讯录人数
	adl.m_size = 0;


	while (1)
	{
		// 菜单调用
		showMenu();

		// 输入选择
		cin >> select;

		// switch 多分支结构
		switch (select)
		{
		case 1:	// 1、添加联系人
			addPerson(&adl);
			break;
		case 2:	// 2、显示联系人
			showPerson(&adl);
			break;
		case 3:	// 3、删除联系人
		//{
		//	/*string name;
		//	cout << "请输入删除联系人姓名: " << endl;
		//	cin >> name;*/
		//	/*if (isExist(&adl, name) != -1)
		//	{
		//		cout << "找到联系人" << endl;
		//	}
		//	else
		//	{
		//		cout << "查无此人" << endl;
		//	}*/
		//}
			deletePerson(&adl);
			break;
		case 4: // 4、查找联系人
			findPerson(&adl);
			break;
		case 5: // 5、修改联系人
			modifyPerson(&adl);
			break;
		case 6: // 6、清空联系人
			cleanPerson(&adl);
			break;
		case 0: // 0、推出通讯录
			cout << "欢迎下次使用" << endl;
			system("pause");
			return 0;
		default:
			break;
		}
	}

	system("pause");

	return 0;
}

附上一句,这次使用了数组,读者有兴趣的话不妨使用链表来存储。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-14 13:50:50  更:2021-08-14 13:53:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 17:38:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计