【C++】通讯录的基本实现,附有源码分享
目录
1、运行环境
2、系统实现功能
2.1菜单功能
2.2退出通讯录功能
2.3添加联系人功能
2.4显示联系人功能
2.5删除联系人功能
2.6查找联系人功能
2.7修改联系人功能
2.8清空联系人功能
2.9动态扩容功能
2.10选择优化功能
2.11文件操作
3、源码分享
1、运行环境
运行环境为:Visual Studio 2022
2、系统实现功能
- 菜单功能:简单的人机交互菜单
- 添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭住址)
- 显示联系人:显示通讯录中所有联系人信息
- 删除联系人:按照姓名进行删除指定联系人
- 查找联系人:按照姓名查看指定联系人信息
- 修改联系人:按照姓名重新修改指定联系人
- 清空联系人:清空通讯录中所有信息
- 退出通讯录:退出当前使用的通讯录
- 动态扩容:动态扩容通讯录保存的上限人数
- 选择优化:使用枚举常量优化switch
- 文件操作:文件保存数据,读取文件数据
实现各种功能之前需要提供关于通讯录的结构体定义,该系统提出人的信息包括姓名,性别,年龄,联系电话和家庭住址,根据上述要求就可以定义出下面相关的结构体,数据大小使用宏定义定义,定义后的结构体用typedef关键字重命名,这样实现看起来更规范一点:
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30typedef struct PeoInFo
{char name[MAX_NAME];char sex[MAX_SEX];int age;char tele[MAX_TELE];char addr[MAX_ADDR];
}PeoInFo;
有了通讯录人的结构体之后,还需要一个管理结构体,这个管理结构体需要包含人的信息,通讯录当前的个数,通讯录的最大容量:
typedef struct Contact
{PeoInFo *data; //指向动态申请的空间,用来存放联系人的信息int sz; //记录的是当前通讯录中有效信息的个数int capacity; //记录当前通讯录的最大容量
}Contact;
2.1菜单功能
百度百科的解释:
菜单最初指餐馆提供的列有各种菜肴的清单。现引申指电子计算机程序进行中出现在显示屏上的选项列表,也指各种服务项目的清单等,含义更为广泛。广义的菜单是指餐厅中一切与该餐饮企业产品、价格及服务有关的信息资料,它不仅包含各种文字图片资料、声像资料以及模型与实物资料,甚至还包括顾客点菜后服务员所写的点菜单。狭义的菜单则指的是餐饮企业为便于顾客点菜订餐而准备的介绍该企业产品、服务与价格等内容的各种印刷品。
菜单功能:为了方便人去选择功能使用
//1、显示菜单界面
void menu()
{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.2退出通讯录功能
功能描述:退出通讯录系统
思路:根据用户不同的选择,进入不同的功能,可以选择switch分支结构,将整个架构进行搭建
当用户选择0时候,执行退出,选择其他先不做操作,也不会退出程序
int input = 0;do{menu();cout << "请输入:>";cin >> input;switch (input){case 1:break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 0:cout << "退出通讯录" << endl;break;default:cout << "选择错误, 重新选择" << endl;break;}} while (input);
2.3添加联系人功能
功能描述: 向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭地址)最多记录4人
实现步骤:设计初始化通讯录函数,主函数初始化通讯录,设计添加联系人功能,在循环中的对应case下使用该函数
//初始化通讯录功能
void InitContact(Contact* pc)
{pc->data = (PeoInFo*)malloc(DEFAULT_SZ * sizeof(PeoInFo));if (pc->data == NULL){return;}pc->sz = 0;pc->capacity = DEFAULT_SZ;
}//添加联系人功能
void AddContact(Contact* pc)
{if (pc->sz == MAX){cout << "通讯录已满,无法添加" << endl;return;}//增加一个人的信息cout << "请输入名字:>" << endl;cin >> pc->data[pc->sz].name;cout << "请输入年龄:>" << endl;cin >> pc->data[pc->sz].age;cout << "请输入性别:>" << endl;cin >> pc->data[pc->sz].sex;cout << "请输入电话:>" << endl;cin >> pc->data[pc->sz].tele;cout << "请输入地址:>" << endl;cin >> pc->data[pc->sz].addr;pc->sz++;printf("增加成功\n");
}
2.4显示联系人功能
功能描述:显示通讯录中已有的联系人信息
在每个功能写完之后,我们都需要测试该功能是否实现,这个时候就需要写出显示函数来查看我们的执行操作和功能函数是否正确运行了:
//显示通讯录功能
void PrintContact(const Contact* pc)
{int i = 0;printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}
2.5删除联系人功能
功能描述:按照姓名进行删除指定联系人
实现步骤:添加一些联系人后,删除指定联系人,利用显示联系人功能函数测试该功能是否正确实现
//删除通讯录信息功能
void DelectContact(Contact* pc)
{char name[MAX_NAME] = { 0 };if (pc->sz == 0){printf("通讯录为空!\n");return;}cout << "请输入要删除的人的名字:>";cin >> name;int pos = -1;for (int i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){pos = i;break;}}if (pos == -1){cout << "要删除的人不存在!" << endl;return;}else{int i = 0;for (i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}}pc->sz--;cout << "删除成功!" << endl;
}
其中可以把查找名字的部分代码封装成找下标的函数:
//查找通讯录指定联系人下标功能
int FindByContact(Contact* pc, char name[])
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}
2.6查找联系人功能
功能描述:按照姓名查看指定联系人信息
实现步骤:设计查找联系人函数,然后测试该功能的作用是否正确实现
//查找通讯录联系人功能
void SeacherContact(Contact* pc)
{char name[MAX_NAME] = { 0 };cout << "请输入要查找的人的名字:>" << endl;cin >> name;int pos = FindByContact(pc, name);if (pos == -1){cout << "要查找的人不存在!" << endl;return;}else{printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n", pc->data[pos].name, pc->data[pos].age,pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);}
}
2.7修改联系人功能
功能描述:按照姓名重新修改指定联系人
实现步骤:查找用户输入的联系人,如果查找成功进行修改操作,查找失败提示查无此人
//更改通讯录联系人信息
void ModifyContact(Contact* pc)
{char name[MAX_NAME] = { 0 };cout << "请输入要修改的人的名字:>";cin >> name;int pos = FindByContact(pc, name);if (pos == -1){cout << "要修改的人不存在!" << endl;return;}else{cout << "请输入名字:>" << endl;cin >> pc->data[pos].name;cout << "请输入年龄:>" << endl;cin >> pc->data[pos].age;cout << "请输入性别:>" << endl;cin >> pc->data[pos].sex;cout << "请输入电话:>" << endl;cin >> pc->data[pos].tele;cout << "请输入地址:>" << endl;cin >> pc->data[pos].addr;cout << "修改成功!" << endl;}
}
2.8清空联系人功能
功能描述:销毁通讯录
//销毁通讯录
void DestoryContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->sz = 0;pc->capacity = 0;
}
2.9动态扩容功能
由于,第一次初始化的时候规定了通讯录的上限人数,但这样有可能会出现人数超过的极端情况,而且在少数联系人的时候会浪费开辟的内存空间,不如改成动态开辟内存空间来的方便和有益:
void CheckContact(Contact* pc)
{if (pc->sz == pc->capacity){PeoInFo* ptr = (PeoInFo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInFo));if (ptr != NULL){pc->data = ptr;pc->capacity += INC_SZ;printf("增容成功!\n");}else{return;}}
}//添加联系人功能
void AddContact(Contact* pc)
{//增容CheckContact(pc);if (pc->sz == MAX){cout << "通讯录已满,无法添加" << endl;return;}//增加一个人的信息cout << "请输入名字:>" << endl;cin >> pc->data[pc->sz].name;cout << "请输入年龄:>" << endl;cin >> pc->data[pc->sz].age;cout << "请输入性别:>" << endl;cin >> pc->data[pc->sz].sex;cout << "请输入电话:>" << endl;cin >> pc->data[pc->sz].tele;cout << "请输入地址:>" << endl;cin >> pc->data[pc->sz].addr;pc->sz++;printf("增加成功\n");
}
2.10选择优化功能
学了枚举之后,枚举常量可以用在switch语句中
enum Option
{EXIT,ADD,PRINT,DEL,SEARCH,MODIFY,DESTORYAVE
};switch (input){case ADD://增加人的信息AddContact(&con);break;case PRINT://显示人的信息PrintContact(&con);break;case DEL://删除人的信息DelectContact(&con);break;case SEARCH://查找人的信息SeacherContact(&con);break;case MODIFY://更改人的信息ModifyContact(&con);break;case DESTORY://清空通讯录信息SaveContact(&con);break;case 0:cout << "退出通讯录" << endl;break;default:cout << "选择错误, 重新选择" << endl;break;}
2.11文件操作
如果没有文件操作,那么我们每次运行程序都需要重新输入数据,这未免太麻烦了。我们可以把我们输入的数据输出到文件里面保存起来,每次运行程序之后都从保存数据的文件读取出所有通讯录数据:
//保存通讯录到文件功能
void SaveContact(Contact* pc)
{FILE* pf;if (fopen_s(&pf, "contact.txt", "w")){return;}int i = 0;for (i = 0; i < pc->sz; i++){fwrite(pc->data + i, sizeof(PeoInFo), 1, pf);}fclose(pf);pf = NULL;
}//读取通讯录文件内容
void LoadContact(Contact* pc)
{FILE* pf; if (fopen_s(&pf, "contact.txt", "r")){return;}PeoInFo tmp = { 0 };while (fread(&tmp, sizeof(PeoInFo), 1, pf)){//检测容量CheckContact(pc);pc->data[pc->sz] = tmp;pc->sz++;}fclose(pf);pf = NULL;
}
3、源码分享
//test.cpp
#include "Contact.h"
int main(void)
{int input = 0;char name[1024] = { 0 };//创建通讯录Contact con;InitContact(&con);LoadContact(&con);do{menu();cout << "请输入:>";cin >> input;switch (input){case ADD://增加人的信息AddContact(&con);break;case PRINT://显示人的信息PrintContact(&con);break;case DEL://删除人的信息DelectContact(&con);break;case SEARCH://查找人的信息SeacherContact(&con);break;case MODIFY://更改人的信息ModifyContact(&con);break;case DESTORY://清空通讯录信息SaveContact(&con);DestoryContact(&con);break;case 0:SaveContact(&con);cout << "退出通讯录" << endl;break;default:cout << "选择错误, 重新选择" << endl;break;}} while (input);SaveContact(&con);return 0;
}
#pragma once
#include <iostream>
#include <cstdio>
#include <fstream>
#include <string>
using namespace std;#define DEFAULT_SZ 3
#define INC_SZ 2
#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 12
#define MAX_ADDR 30typedef struct PeoInFo
{char name[MAX_NAME];char sex[MAX_SEX];int age;char tele[MAX_TELE];char addr[MAX_ADDR];
}PeoInFo;typedef struct Contact
{PeoInFo* data; //指向动态申请的空间,用来存放联系人的信息int sz; //记录的是当前通讯录中有效信息的个数int capacity; //记录当前通讯录的最大容量
}Contact;enum Option
{EXIT,ADD,PRINT,DEL,SEARCH,MODIFY,DESTORY
};void menu();void InitContact(Contact* pc);void PrintContact(const Contact* pc);void DelectContact(Contact* pc);int FindByContact(Contact* pc, char name[]);void SeacherContact(Contact* pc);void ModifyContact(Contact* pc);void DestoryContact(Contact* pc);void CheckContact(Contact* pc);void AddContact(Contact* pc);void SaveContact(Contact* pc);void LoadContact(Contact* pc);
#include "Contact.h"//显示菜单界面
void menu()
{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;
}//初始化通讯录功能
void InitContact(Contact* pc)
{pc->data = (PeoInFo*)malloc(DEFAULT_SZ * sizeof(PeoInFo));if (pc->data == NULL){return;}pc->sz = 0;pc->capacity = DEFAULT_SZ;
}//添加联系人功能
//void AddContact(Contact* pc)
//{
// if (pc->sz == MAX)
// {
// cout << "通讯录已满,无法添加" << endl;
// return;
// }
// //增加一个人的信息
// cout << "请输入名字:>" << endl;
// cin >> pc->data[pc->sz].name;
// cout << "请输入年龄:>" << endl;
// cin >> pc->data[pc->sz].age;
// cout << "请输入性别:>" << endl;
// cin >> pc->data[pc->sz].sex;
// cout << "请输入电话:>" << endl;
// cin >> pc->data[pc->sz].tele;
// cout << "请输入地址:>" << endl;
// cin >> pc->data[pc->sz].addr;
//
// pc->sz++;
// printf("增加成功\n");
//}//显示通讯录功能
void PrintContact(const Contact* pc)
{int i = 0;printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据for (i = 0; i < pc->sz; i++){printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].tele,pc->data[i].addr);}
}//删除通讯录信息功能
void DelectContact(Contact* pc)
{char name[MAX_NAME] = { 0 };if (pc->sz == 0){printf("通讯录为空!\n");return;}cout << "请输入要删除的人的名字:>";cin >> name;int pos = -1;for (int i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){pos = i;break;}}if (pos == -1){cout << "要删除的人不存在!" << endl;return;}else{int i = 0;for (i = pos; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}}pc->sz--;cout << "删除成功!" << endl;
}//查找通讯录指定联系人下标功能
int FindByContact(Contact* pc, char name[])
{int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;}}return -1;
}//查找通讯录联系人功能
void SeacherContact(Contact* pc)
{char name[MAX_NAME] = { 0 };cout << "请输入要查找的人的名字:>" << endl;cin >> name;int pos = FindByContact(pc, name);if (pos == -1){cout << "要查找的人不存在!" << endl;return;}else{printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");//打印数据printf("%-20s\t%-5d\t%-5s\t%-12s\t%-20s\n", pc->data[pos].name, pc->data[pos].age,pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);}
}//更改通讯录联系人信息
void ModifyContact(Contact* pc)
{char name[MAX_NAME] = { 0 };cout << "请输入要修改的人的名字:>";cin >> name;int pos = FindByContact(pc, name);if (pos == -1){cout << "要修改的人不存在!" << endl;return;}else{cout << "请输入名字:>" << endl;cin >> pc->data[pos].name;cout << "请输入年龄:>" << endl;cin >> pc->data[pos].age;cout << "请输入性别:>" << endl;cin >> pc->data[pos].sex;cout << "请输入电话:>" << endl;cin >> pc->data[pos].tele;cout << "请输入地址:>" << endl;cin >> pc->data[pos].addr;cout << "修改成功!" << endl;}
}//销毁通讯录
void DestoryContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->sz = 0;pc->capacity = 0;
}void CheckContact(Contact* pc)
{if (pc->sz == pc->capacity){PeoInFo* ptr = (PeoInFo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInFo));if (ptr != NULL){pc->data = ptr;pc->capacity += INC_SZ;cout << "增容成功!" << endl;}else{return;}}
}//添加联系人功能
void AddContact(Contact* pc)
{//增容CheckContact(pc);if (pc->sz == MAX){cout << "通讯录已满,无法添加" << endl;return;}//增加一个人的信息cout << "请输入名字:>" << endl;cin >> pc->data[pc->sz].name;cout << "请输入年龄:>" << endl;cin >> pc->data[pc->sz].age;cout << "请输入性别:>" << endl;cin >> pc->data[pc->sz].sex;cout << "请输入电话:>" << endl;cin >> pc->data[pc->sz].tele;cout << "请输入地址:>" << endl;cin >> pc->data[pc->sz].addr;pc->sz++;printf("增加成功\n");
}//保存通讯录到文件功能
void SaveContact(Contact* pc)
{FILE* pf;if (fopen_s(&pf, "contact.txt", "w")){return;}int i = 0;for (i = 0; i < pc->sz; i++){fwrite(pc->data + i, sizeof(PeoInFo), 1, pf);}fclose(pf);pf = NULL;
}//读取通讯录文件内容
void LoadContact(Contact* pc)
{FILE* pf; if (fopen_s(&pf, "contact.txt", "r")){return;}PeoInFo tmp = { 0 };while (fread(&tmp, sizeof(PeoInFo), 1, pf)){//检测容量CheckContact(pc);pc->data[pc->sz] = tmp;pc->sz++;}fclose(pf);pf = NULL;
}