C++实现通讯录管理系统:从结构设计到完整代码详解
基于C++标准库构建的控制台通讯录系统,利用结构体存储联系人信息(姓名、性别、年龄、电话、地址),通过结构体数组管理数据。文章详细解析了主菜单逻辑及增加、查询、删除、修改、显示、清空等功能的具体算法与代码实现,提供可直接编译运行的完整源代码。
通讯录系统的整体架构
实现一个具备基础增删改查功能的通讯录系统,首先需要定义数据存储的核心结构。通讯录不仅需要存储联系人的详细信息,还需要记录当前已保存的联系人数,以便动态控制数组的使用情况。
第1步:定义数据结构
目的:确定每个联系人的属性及通讯录本身的容器属性。
动作:创建两个结构体。person用于存储单个联系人的姓名、性别、年龄、电话和地址。其中性别采用整型标识(1代表男,2代表女)以简化输入验证。另一个结构体 addressBooks 作为通讯录容器,内部包含一个最大容量为 1000 的 person 类型数组,以及一个记录当前有效人数的变量 m_size。
关键点:person 结构体必须在 addressBooks 之前定义,否则编译器会因未知类型而报错。同时需引入 <iostream> 并使用 std 命名空间。
#define Max 1000
struct person
{
string m_Name;
string m_Sex; // 1为男,2为女
int m_age;
string m_phone;
string m_Address;
};
struct addressBooks
{
struct person personArray[Max]; // 内部保存联系人的数组
int m_size = 0; // 当前通讯录中人员个数,初始化为0
};
第2步:设计系统菜单与交互流程
目的:提供用户友好的命令行界面,并处理功能选择逻辑。
入口:主函数 main。
动作:
- 定义
showMenu()函数,打印包含各功能编号的菜单列表。使用制表符\t进行简单排版。
2. 在
main 函数中初始化一个 addressBooks 类型的变量作为通讯录实例。
3. 使用 while(1) 构建主循环,只要不执行退出操作,程序将持续运行。
4. 每次循环先调用 showMenu(),然后读取用户的整数输入 select。switch-case 语句分发任务。由于涉及对通讯录数据的修改,所有功能函数均通过指针(或引用)传递 addressBooks 的地址,以确保函数内部的操作能反映到主函数的变量上。void showMenu()
{
cout << "\t*************************" << endl;
cout << "\t***** 1、添加联系人 *****" << endl;
cout << "\t***** 2、显示联系人 *****" << endl;
cout << "\t***** 3、查找联系人 *****" << endl;
cout << "\t***** 4、修改联系人 *****" << endl;
cout << "\t***** 5、删除联系人 *****" << endl;
cout << "\t***** 6、清空通讯录 *****" << endl;
cout << "\t***** 0、退出通讯录 *****" << endl;
cout << "\t*************************" << endl;
}
int main()
{
addressBooks abc;
while (1) {
showMenu();
int select = 0;
cout << "请选择你的操作:";
cin >> select;
switch (select)
{
case 1: addPerson(&abc); break;
case 2: showPerson(&abc); break;
case 3: findPerson(&abc); break;
case 4: modifyPerson(&abc); break;
case 5: deletePerson(&abc); break;
case 6: clearPerson(&abc); break;
case 0: cout << "欢迎下次使用" << endl; return 0; break;
default: cout << "请输入正确的选项" << endl; break;
}
}
}
六大核心功能实现细节
第1步:实现添加联系人功能
入口:addPerson(addressBooks* abc)
动作与参数:
- 容量检查:首先判断
abc->m_size >= Max,若已满则提示失败。 - 信息录入:按顺序提示用户输入姓名、性别、年龄、电话和地址。
- 数据校验:对于性别输入,使用
while循环确保仅接受 1 或 2,非法输入会重新提示。 - 写入数组:将输入的数据存入
abc->personArray[abc->m_size]对应的位置。 - 更新计数:赋值完成后,执行
abc->m_size++。
void addPerson(addressBooks* abc)
{
if (abc->m_size >= Max)
{
cout << "通讯录已满,添加失败" << endl;
}
else {
string name; cout << "添加联系人名字:" << endl; cin >> name;
abc->personArray[abc->m_size].m_Name = name;
int sex = 0;
cout << "联系人性别为:" << endl << "1---男\n2---女\n";
cin >> sex;
while (1) {
if (sex == 1 || sex == 2) break;
cout << "输入有误,请在数字 1和2中选择" << endl; cin >> sex;
}
// 根据数字转换为字符串存储
abc->personArray[abc->m_size].m_Sex = (sex == 1 ? "男" : "女");
int age; cout << "联系人年龄为:" << endl; cin >> age;
abc->personArray[abc->m_size].m_age = age;
string phoneNumber; cout << "联系人电话:" << endl; cin >> phoneNumber;
abc->personArray[abc->m_size].m_phone = phoneNumber;
string address; cout << "联系人地址为:" << endl; cin >> address;
abc->personArray[abc->m_size].m_Address = address;
cout << "添加成功" << endl;
abc->m_size++; // 更新人数
system("pause"); system("cls"); // 暂停并按清屏
}
}
第2步:实现显示联系人功能
入口:showPerson(addressBooks* abc)
动作:遍历 0 到 m_size-1 的索引范围,输出数组中每个成员的所有属性。如果 m_size 为 0,则提示“当前记录为空”。
void showPerson(addressBooks* abc)
{
if (abc->m_size == 0) {
cout << "当前记录为空" << endl;
} else {
for (int i = 0; i < abc->m_size; i++) {
cout << "姓名:" << abc->personArray[i].m_Name
<< "\t性别:" << abc->personArray[i].m_Sex
<< "\t年龄:" << abc->personArray[i].m_age
<< "\t电话:" << abc->personArray[i].m_phone
<< "\t地址:" << abc->personArray[i].m_Address
<< endl;
}
}
system("pause"); system("cls");
}
第3步:实现查找联系人功能
入口:findPerson(addressBooks* abc)
动作:
- 接收用户输入的姓名。
- 调用辅助函数
isExit在数组中进行线性扫描。 - 若找到匹配项,返回其下标;否则返回 -1。
- 根据返回值判断是否存在,存在则输出详情,不存在则提示“查无此人”。
// 辅助判定函数
int isExit(addressBooks* abc, string name)
{
for (int i = 0; i < abc->m_size; i++)
{
if (abc->personArray[i].m_Name == name) return i;
}
return -1;
}
void findPerson(addressBooks* abc)
{
string name;
cout << "输入要查找联系人的名字:" << endl;
cin >> name;
int i = isExit(abc, name);
if (i != -1)
{
// 输出该索引下的详细信息... (逻辑同显示功能)
cout << "查找成功:" << abc->personArray[i].m_Name << endl;
}
else {
cout << "查无此人" << endl;
}
system("pause"); system("cls");
}
第4步:实现修改联系人功能
入口:modifyPerson(addressBooks* abc)
动作:复用 isExit 查找指定姓名的联系人下标。若找到(返回值不为 -1),则覆盖该下标处结构体的各项成员变量;若未找到,提示错误。注意局部变量名避免冲突(如内层 name 变量可另取名为 newName)。
第5步:实现删除联系人功能
入口:deletePerson(addressBooks* abc)
操作:
- 风险提醒:删除会导致数组元素位置变动,需小心处理边界。
- 定位:使用
isExit获取待删除者的索引v。 - 前移:从索引
v开始,将后续元素逐个向前移动一位(array[i] = array[i+1]),直至末尾。 - 缩减:最后将计数器
m_size减 1,彻底“移除”最后一个冗余项。
void deletePerson(addressBooks* abc)
{
if (abc->m_size == 0) {
cout << "通讯录为空" << endl;
return;
}
string name;
cout << "输入要删除的联系人:" << endl;
cin >> name;
int v = isExit(abc, name);
if (v != -1) {
// 元素前移
for (int i = v; i < abc->m_size - 1; i++) {
abc->personArray[i] = abc->personArray[i + 1];
}
abc->m_size--; // 减小总人数
cout << "删除成功" << endl;
} else {
cout << "查无此人" << endl;
}
system("pause"); system("cls");
}
第6步:实现清空通讯录功能
入口:clearPerson(addressBooks* abc)
动作:直接将 abc->m_size 重置为 0。虽然内存中仍有旧数据,但由于计数为 0,系统逻辑上视为空,且后续新增数据会直接覆盖旧位。
void clearPerson(addressBooks* abc)
{
abc->m_size = 0;
cout << "通讯录已清空" << endl;
system("pause"); system("cls");
}
完整源码结构参考
在实际工程开发中,通常会将类的声明放在头文件(如 Txl.h),而具体实现放在源文件(如 Txl.cpp)。以下展示了模块化的组织方式,这有助于提高代码可读性:
// Txl.h
#pragma once
#include<iostream>
using namespace std;
#define Max 1000
struct person { /* 定义同上 */ };
struct addressBooks { /* 定义同上 */ };
// 函数声明
void addPerson(addressBooks* abc);
void showPerson(addressBooks* abc);
int isExit(addressBooks* abc, string name);
void deletePerson(addressBooks* abc);
void findPerson(addressBooks* abc);
void modifyPerson(addressBooks* abc);
void clearPerson(addressBooks* abc);
程序编译与生成
完成代码编写后,在集成开发环境(IDE)中选择 Release 配置进行编译。生成的可执行文件(.exe)位于项目的 debug 或 release 文件夹中。双击即可独立运行,无需安装 C++ 运行库环境(取决于编译配置),便于在不同计算机间分享演示。
以上就是C++实现通讯录管理系统的详细内容,更多关于C++结构体应用与控制台开发的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













