通讯录动态版本的实现(源码+分析)
2021-09-11 23:50
323 查看
文章目录
通讯录功能
实现的通讯录为一个动态增加版本的通讯录,该通讯录能够通过需求自行的增加存放联系人的数量,主要功能为:
1.能够根据需求(要存多少联系人就给多少空间)存放联系人信息
联系人的信息:姓名+性别+年龄+电话+地址
2.能够增加人的信息
3.能够删除指定人的信息
4.能够查找指定人的信息
5.能够修改指定人的信息
6.能够显示通讯录
关键功能的实现
1.创建和初始化通讯录
创建通讯录:通讯录能够保存联系人的多个信息,所以我们先创建一个结构体,这个结构体能够包含一个人的所有信息,定义为 struct PeoInfo ;紧接着在创建一个通讯录,这个通讯录能够存放联系人,且能够记录通讯录的人数,所以再创建一个嵌套的结构体,定义为 struct Contact 。
代码如下:
struct PeoInfo(为了后期的使用方便,将其重定义为 PeoInfo )
typedef struct PeoInfo { char name[MAX_NAME]; char sex[SEX]; int age; char tele[MAX_TELE]; char addr[MAX_ADDR]; } PeoInfo;
struct Contact(为了后期的使用方便,将其重定义为 Contact )
typedef struct Contact { PeoInfo* data;//结构体指针,指向结构体 PeoInfo int sz;//sz用来记录通讯录扩容前联系人的人数 int capacity;//capacity用来记录扩容后该通讯录的最大容量(即最大能存多少联系人) }Contact;
初始化通讯录:我们规定通讯录最开始能够存放3人(可自行规定)。
如下:
void InitContact(Contact* pc) { pc->data = (PeoInfo*) malloc(MAX_SZ*sizeof(PeoInfo));//通过动态内存函数来定义存放联系人的数目 if (pc->data == NULL) { perror("InitContact");//当开辟内存失败时,打印出错误信息 return; } pc->sz = 0; pc->capacity = MAX_SZ; }
2.增加联系人
void AddContact(Contact* pc) { if (pc->sz == pc->capacity)//判断若存储的通讯录人数已达到最大容量,则进行动态增容 { //通过realloc函数动态的增加通讯录容量 PeoInfo* ptr=(PeoInfo*)realloc(pc->data, (ADD_CAP + pc->capacity) * sizeof(PeoInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity += ADD_CAP;//规定每次当通讯录满时,则增加2个人的容量 printf("增容成功!\n"); } else { printf("增容失败\n"); return; } } printf("请输入姓名:>"); scanf("%s", pc->data[pc->sz].name);//通过指针来访问结构体成员,下同 printf("请输入性别:>"); scanf("%s", pc->data[pc->sz].sex); printf("请输入年龄:>"); scanf("%d", &(pc->data[pc->sz].age)); printf("请输入电话:>"); scanf("%s", pc->data[pc->sz].tele); printf("请输入地址:>"); scanf("%s", pc->data[pc->sz].addr); pc->sz++; printf("增加成功!\n"); }
3.删除联系人
注:在实现删除功能前,需先找到要删除联系人的信息,所以,在删除前要多增加一个函数,该函数用来找到被删除联系人。
static int FindContact(const Contact* pc,char name[])//找到被删除联系人,且该函数用static修饰保证只能在该文件内使用 { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(name, (pc->data[i]).name) == 0) return i;//返回该联系人在通讯录中的位置 } return -1; } void DelContact(Contact* pc)//删除联系人 { char name[MAX_NAME] = { 0 }; printf("请输入要删除的联系人:>"); scanf("%s", name); int x = FindContact(pc,name); if (x < 0) { printf("没找到联系人\n"); } else { int i = 0; for (i = x; x < pc->sz - 1; x++) { pc->data[x] = pc->data[x + 1];//实现删除的功能即为用后一个联系人的信息覆盖前一个联系人的信息 } pc->sz--;//删除完成后,通讯录减少一人 printf("删除成功!\n"); } }
4.查找联系人
在查找联系人之前,需先知道被查找人在通讯录中的位置,所以在实现查找功能的函数中也需用到 FindContact 函数来寻找联系人所在的位置。
void SearchContact(Contact* pc) { char name[MAX_NAME] = { 0 }; printf("请输入要查找的联系人:>"); scanf("%s", name); int x = FindContact(pc, name);//x为被查找的联系人的位置 if (x < 0) { printf("没找到联系人\n"); } else { printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "地址"); printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\t\n", pc->data[x].name, pc->data[x].sex, pc->data[x].age, pc->data[x].tele, pc->data[x].addr); } }
5.修改联系人
同删除、查找一样,在修改前需知道被修改联系人的位置,用 FindContact 函数来返回位置。
void ModifyContact(Contact* pc) { char name[MAX_NAME] = { 0 }; printf("请输入要修改的联系人:>"); scanf("%s", name); int x = FindContact(pc, name);//x就为被修改人的位置 if (x < 0) { printf("没找到联系人\n"); } else { printf("请输入姓名:>"); scanf("%s", pc->data[x].name); printf("请输入性别:>"); scanf("%s", pc->data[x].sex); printf("请输入年龄:>"); scanf("%d", &(pc->data[x].age)); printf("请输入电话:>"); scanf("%s", pc->data[x].tele); printf("请输入地址:>"); scanf("%s", pc->data[x].addr); printf("修改成功!\n"); } }
代码总览
为了更好的实现通讯录,我们将程序分三个文件,分别是:
test.c —— 测试通讯录的模块
contact.h —— 类型定义,函数声明
contact.c —— 函数的实现
test.c
#include"contact.h" //引用头文件 void menu() { printf("***************************\n"); printf("*** 1.Add 2.Del ***\n"); printf("*** 3.Search 4.Modify***\n"); printf("*** 5.Print ***\n"); printf("*** 0.Exit ***\n"); printf("***************************\n"); } enum Option //将每个功能的名称定义为一个枚举类型的成员,使辨识度更高 { EXIT, ADD, DEL, SEARCH, MODIFY, PRINT, }; int main() { Contact con; InitContact(&con); int input = 0; do { menu(); scanf("%d", &input); switch (input) { case ADD: AddContact(&con);//添加联系人 break; case DEL: DelContact(&con);//删除联系人 break; case SEARCH: SearchContact(&con);//查找联系人 break; case MODIFY: ModifyContact(&con);//修改联系人 break; case PRINT: PrintContact(&con);//显示通讯录 break; case EXIT: DestoryContact(&con);//销毁通讯录 printf("退出通讯录\n"); break; default: printf("选择错误,请重新选择:"); break; } } while (input); return 0; }
contact.h
#include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX_NAME 20 #define SEX 10 #define MAX_ADDR 100 #define MAX_TELE 12 #define MAX_SZ 3 #define ADD_CAP 2 #define MAX 1000 typedef struct PeoInfo { char name[MAX_NAME]; char sex[SEX]; int age; char tele[MAX_TELE]; char addr[MAX_ADDR]; } PeoInfo; //重定义为了使用方便,下同 typedef struct Contact { PeoInfo* data; int sz; int capacity; }Contact; //重定义 void InitContact(Contact* pc); //初始化通讯录 void AddContact(Contact* pc); //增加联系人 void PrintContact(const Contact* pc); //打印通讯录 void DelContact(Contact* pc); //删除联系人 void SearchContact(Contact* pc); //查找联系人 void ModifyContact(Contact* pc); //修改联系人 void DestoryContact(Contact* pc); //销毁通讯录
contact.c
#include"contact.h" void InitContact(Contact* pc) { pc->data = (PeoInfo*) malloc(MAX_SZ*sizeof(PeoInfo)); if (pc->data == NULL) { perror("InitContact"); return; } pc->sz = 0; pc->capacity = MAX_SZ; } void DestoryContact(Contact* pc) { free(pc->data); pc->data = NULL; pc->sz = 0; pc->capacity = 0; } void AddContact(Contact* pc) { if (pc->sz == pc->capacity) { PeoInfo* ptr=(PeoInfo*)realloc(pc->data, (ADD_CAP + pc->capacity) * sizeof(PeoInfo)); if (ptr != NULL) { pc->data = ptr; pc->capacity += ADD_CAP; printf("增容成功!\n"); } else { printf("增容失败\n"); return; } } printf("请输入姓名:>"); scanf("%s", pc->data[pc->sz].name); printf("请输入性别:>"); scanf("%s", pc->data[pc->sz].sex); printf("请输入年龄:>"); scanf("%d", &(pc->data[pc->sz].age)); printf("请输入电话:>"); scanf("%s", pc->data[pc->sz].tele); printf("请输入地址:>"); scanf("%s", pc->data[pc->sz].addr); pc->sz++; printf("增加成功!\n"); } void PrintContact(const Contact* pc) { printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "地址"); int i = 0; for (i = 0; i < pc->sz; i++) { printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\t\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr); } } static int FindContact(const Contact* pc,char name[]) { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(name, (pc->data[i]).name) == 0) return i; } return -1; } void DelContact(Contact* pc) { char name[MAX_NAME] = { 0 }; printf("请输入要删除的联系人:>"); scanf("%s", name); int x = FindContact(pc,name); if (x < 0) { printf("没找到联系人\n"); } else { int i = 0; for (i = x; x < pc->sz - 1; x++) { pc->data[x] = pc->data[x + 1]; } pc->sz--; printf("删除成功!\n"); } } void SearchContact(Contact* pc) { char name[MAX_NAME] = { 0 }; printf("请输入要查找的联系人:>"); scanf("%s", name); int x = FindContact(pc, name); if (x < 0) { printf("没找到联系人\n"); } else { printf("%-20s\t%-5s\t%-5s\t%-12s\t%-20s\t\n", "姓名", "性别", "年龄", "电话", "地址"); printf("%-20s\t%-5s\t%-5d\t%-12s\t%-20s\t\n", pc->data[x].name, pc->data[x].sex, pc->data[x].age, pc->data[x].tele, pc->data[x].addr); } } void ModifyContact(Contact* pc) { char name[MAX_NAME] = { 0 }; printf("请输入要修改的联系人:>"); scanf("%s", name); int x = FindContact(pc, name); if (x < 0) { printf("没找到联系人\n"); } else { printf("请输入姓名:>"); scanf("%s", pc->data[x].name); printf("请输入性别:>"); scanf("%s", pc->data[x].sex); printf("请输入年龄:>"); scanf("%d", &(pc->data[x].age)); printf("请输入电话:>"); scanf("%s", pc->data[x].tele); printf("请输入地址:>"); scanf("%s", pc->data[x].addr); printf("修改成功!\n"); } }
运行效果
相关文章推荐
- Mybatis3源码分析(21)-Mapper实现-动态代理
- SprignMVC+myBatis整合+mybatis源码分析+动态代理实现流程+如何根据mapper接口生成其实现类
- MTK平台CPU/GPU动态调频的实现之PerfService的源码分析
- JAVA 动态代理(proxy)的实现和源码分析
- 【c语言】通讯录的简单实现文件版本(动态开辟内存)
- 实现动态版本通讯录(在简易通讯录的基础上)
- JNI源码分析 (并实现JNI动态注册)
- Mysql Innodb中undo-log和MVCC多版本一致性读的实现(源码分析)
- mybatis源码分析(5)-----拦截器的实现原理(动态代理+责任链)
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机动态迁移源码分析
- JNI源码分析 (并实现JNI动态注册)
- Jdk1.8版本Semaphore实现源码分析
- 实现一个动态版本通讯录; 通讯录可以增加容量
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机动态迁移源码分析
- Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理
- OpenStack基于Libvirt的虚拟化平台调度实现----Nova虚拟机动态迁移源码分析
- Dubbo源码分析(六):Dubbo内核实现之动态编译
- function 源码分析1--boost function缩水版本实现
- Java动态代理详解,以及底层JDK源码实现分析(基于Java8)。
- 将结构体实现的简易通讯录改成动态的版本