前言 : 在生活中我们经常会遇到通讯录的使用,比如存进一个新的联系人的信息,或者对其删除,修改,查找;那这些神奇的功能是如何实现的?我们不禁好奇。今天,这篇博文将教会大家实现一个静态的或者动态的通讯录,以后我们就可以靠自己实现一个通讯录啦 ~
目录一览- 1.静态通讯录讲解
- 1.1 静态通讯录的功能列表的实现(text.c)
- 1.1.1 菜单的实现
- 1.1.2 菜单功能的枚举
- 1.1.3 main函数的实现
- 1.2 静态通讯录各个函数的声明包含 (contact.h)
- 1.2.1 #define 定义各个标号以及头文件的引用
- 1.2.2 定义联系人信息结构体
- 1.2.3定义静态通讯录结构体
- 1.2.4 各个功能函数的声明
- 1.3 功能函数的实现讲解 (contact.c)
- 1.3.1 静态通讯录初始化函数讲解
- 1.3.2 Add新增联系人函数的实现讲解
- 1.3.3 展示当前存入的联系人信息函数讲解
- 1.3.4 通过姓名查找当前存放进去的联系人信息位置函数实现讲解
- 1.3.5 删除指定联系人函数实现讲解
- 1.3.6 查找指定联系人函数实现讲解
- 1.3.7 修改指定联系人信息函数实现讲解
- 2.动态通讯录实现讲解
- 2.1 动态通讯录结构体实现
- 2.2 初始化动态通讯录函数讲解
- 2.3 动态通讯录新增联系人函数实现讲解
- 2.4 退出(销毁动态开辟的内存空间)通讯录函数实现讲解
- 3.整体工程源代码展示
- 3.1 text.c
- 3.2 contact .c
- 3.3 contact.h
- 4.尾声
这里我们实现一个简易的功能菜单,运用print语句即可
功能有 1.新增联系人 2.删除联系人 3.查找指定联系人
4.修改指定联系人信息 5.展示目前存入的联系人 6.对联系人按照一定的标准排序 以及 0.退出通讯录
void menu()
{
printf("*******************************n");
printf("**** 1.add 2.del *****n");
printf("**** 3.search 4.modify *****n");
printf("**** 5.show 6.sort *****n");
printf("**** 0.exit *****n");
printf("*******************************n");
}
1.1.2 菜单功能的枚举
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
EXIT 从0开始向下递增,分别对应菜单上的各个功能,目的是为了下面的switch接口能更加方便直观看出各个功能,以防出错。
1.1.3 main函数的实现这一块我们实现从键盘上输入各个数字代表不同功能,再实现循环输入,
代码如下:
int main()
{
int input = 0;
struct Contact con;
InitContact(&con);
do {
menu();
printf("请选择->");
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 SHOW:
ShowContact(&con);
break;
case EXIT:
//销毁通讯录
DestroyContact(&con);
printf("退出通讯录n");
break;
default:
printf("选择错误n");
break;
}
} while (input);
return 0;
}
1.2 静态通讯录各个函数的声明包含 (contact.h)
1.2.1 #define 定义各个标号以及头文件的引用
#define DEFAULT_SZ 3 #define NAME_MAX 30 #define SEX_MAX 5 #define TELE_MAX 12 #define ADDR_MAX 30 #define MAX 1000
分别定义了
默认存放联系人数量为3 (后面动态通讯录会使用到)
名字数组最大长度为 30‘
性别数组最大长度为 5
电话数组最大长度为 15
地址数组最大长度为 30
静态通讯录能存放最大联系人为 1000
头文件的引用:
#include#include #include #include
引用整个工程所要使用到的函数头文件,避免重复引用(每个文件前面加上 #include "contact.h),这样就实现所有声明头文件放在一个头文件中,分开管理,提升工程书写效率;
1.2.2 定义联系人信息结构体struct PeoInfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
};
1.2.3定义静态通讯录结构体
// 静态通讯录版本
struct Contact
{
struct PeoInfo date[MAX];
int sz;
};
包含了可以存放1000个人信息的联系人结构体以及当前存放进去的有效联系人个数 sz ;
1.2.4 各个功能函数的声明// 初始化通讯录 void InitContact(struct Contact* pc); //增加人的信息 void Addcontact(struct Contact* pc); //显示联系人 void ShowContact(struct Contact*pc); //删除指定联系人 void DelContact(struct Contact* pc); //查找指定联系人 void SearchContact(struct Contact* pc); //修改指定联系人 void ModifyContact(struct Contact* pc); //销毁通讯录 void DestroyContact(struct Contact* pc);1.3 功能函数的实现讲解 (contact.c) 1.3.1 静态通讯录初始化函数讲解
// 静态直接开辟存放1000个人信息的版本
void InitContact(struct Contact* pc)
{
pc->sz = 0; //默认没有信息
memset(pc->date, 0, MAX * sizeof(struct PeoInfo));
//memset(pc->date, 0, sizeof(pc->date));
}
结构体传参,传的一般是结构体地址,结构体指针接受,实现对结构体本身的修改 。(传址调用)
初始化有效联系人个数sz为0;
用memset内存设置函数,将1000个联系人信息结构体初始化为0;
// 静态版本
void Addcontact(struct Contact* pc)
{
struct Contact tmp = { 0 };
if (pc->sz == MAX)
{
printf("通讯录可用空间已满n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
printf("添加成功n");
pc->sz++;
}
}
用pc->date[pc->sz].xxx找到各个联系人信息位置,将信息存入
后有效联系人个数sz++;
实现对下一个联系人信息的存放
void ShowContact(struct Contact* pc)
{
int i = 0;
printf("%15st%5st%8st%15st%30sn",
"name", "age", "sex", "tele", "addr");
for (i = 0; i < pc->sz; i++)
{
//打印每一个数据
printf("%15st%5dt%8st%15st%30sn",
pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
printf("%15st%5st%8st%15st%30sn",
“name”, “age”, “sex”, “tele”, “addr”);
实现初始化联系人信息表头的域宽
接下来打印每一个数据即可;
int FindContactByName(const struct Contact* pc, const char* name)
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
strcmp库函数实现对字符串的比较,相同的话返回数字0;
返回数字0即代表查找成功,此时返回位置 i 即可;
查找不成功返回-1;
void DelContact(struct Contact* pc)
{
if (pc->sz == 0) //有效联系人个数为0
{
printf("通讯录为空,无法删除n");
return;
}
char name[NAME_MAX] = {0};
printf("请输入要删除人的名字:>");
scanf("%s", name);
// 查找
int pos=FindContactByName(pc, name);
if (pos == -1)
{
printf("指定的联系人不存在n");
}
else
{
// 删除
//将数组中要被删除的元素后面的元素相应向前放
int j = 0;
for (j = pos; jsz-1; j++)
{
pc->date[j] = pc->date[j + 1];
}
pc->sz--;
printf("删除成功n");
}
}
相应讲解在代码中以注释形式给出;
1.3.6 查找指定联系人函数实现讲解void SearchContact(const struct Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要查找的联系人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("查无此人n");
}
else
{
printf("%15st%5st%8st%15st%30sn",
"name", "age", "sex", "tele", "addr");
printf("%15st%5dt%8st%15st%30sn",
pc->date[pos].name,
pc->date[pos].age,
pc->date[pos].sex,
pc->date[pos].tele,
pc->date[pos].addr);
}
}
查找成功的话将此位置(pos)打印出即可,格式和增加联系人函数的类似;
1.3.7 修改指定联系人信息函数实现讲解void ModifyContact(struct Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要修改的联系人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("要修改的联系人不存在n");
}
else
{
printf("请输入新的名字:>");
scanf("%s", pc->date[pos].name);
printf("请输入新的年龄:>");
scanf("%d", &(pc->date[pos].age));
printf("请输入新的性别:>");
scanf("%s", pc->date[pos].sex);
printf("请输入新的电话:>");
scanf("%s", pc->date[pos].tele);
printf("请输入新的地址:>");
scanf("%s", pc->date[pos].addr);
printf("修改成功n");
}
}
查找指定联系人成功的话,将此位置(pos)对应的联系人信息修改即可,
格式依旧和新增联系人函数类似;
到此为止,静态通讯录各个模块实现讲解基本完毕;
我们大致可以看一下效果 ;
动态通讯录与静态通讯录实现上大致相同,我们就把不同的地方区分出来进行详细讲解 :
动态通讯录与静态通讯录区别就在于: 静态通讯录一开始就创建好一个可以存放1000个人信息的空间,存不满的话对内存浪费就会比较大;
而动态通讯录可以实现随着放入的联系人信息的增多而相应的增加内存空间,用malloc函数实现,这样对内存空间的浪费就避免了,是更好的实现方法,下面我们就对动态通讯录进行讲解 :
//动态通讯录版本
struct Contact
{
struct PeoInfo* date;
int sz;
int capacity;
};
实现一个 date结构体指针,指向联系人信息结构体
实现一个当前有效联系人信息个数 sz
实现一个当前通讯录最大联系人容量 capacity
// 动态开辟的版本
void InitContact(struct Contact* pc)
{
pc->sz = 0;
pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
pc->capacity = DEFAULT_SZ; // 3
}
有效联系人个数sz制为0;
pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
malloc函数实现一开始动态内存开辟3个联系人空间大小,写法上
DEFAULT_SZ (元素个数:3)* sizeof(struct PeoInfo)(每个元素的大小)
返回开辟空间的地址,date结构体指针来接收;
一开始最大容量capacity制为 3 ;
2.3 动态通讯录新增联系人函数实现讲解动态通讯录与静态通讯录不同就在新增联系人函数实现方式上有所变化,
其他函数一致保持不变 ;
// 动态版本
void Addcontact(struct Contact* pc)
{
// 空间满了就扩容
if (pc->sz == pc->capacity)
{
struct PeoInfo* ptr=(struct PeoInfo*)realloc(pc->date, (pc->capacity + 2) * sizeof(struct PeoInfo));
if (ptr != NULL) // 扩容成功的话
{
pc->date = ptr; // 扩容出来的新地址 ptr 赋给 date
pc->capacity += 2; // 相应最大容量 +2
printf("扩容成功n");
}
else
{
return; // 返回空指针 null 则 return
}
}
// 录入新增人的信息
// 实现上和静态通讯录无异
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
printf("添加成功n");
pc->sz++;
}
struct PeoInfo* ptr=(struct PeoInfo*)realloc(pc->date, (pc->capacity + 2) * sizeof(struct PeoInfo));
扩容代码讲解:如果空间满了就用realloc函数实现扩容,realloc函数的意思是扩容为xx,不是扩容xx ;
realloc函数传入需要扩容的地址dete,扩容一次扩容+2个联系人空间,pc->capacity + 2,每个联系人大小为 sizeof(struct PeoInfo) ;
返回的地址强制类型转换为 (struct PeoInfo*)
存放在结构体指针 ptr 中 ;
其他讲解在代码中以注释形式给出 ;
void DestroyContact(struct Contact* pc)
{
free(pc->date);
pc->date = NULL;
pc->sz = 0;
pc->capacity = 0;
}
释放+制空:
free(pc->date);
pc->date = NULL;
实现避免对内存空间的浪费使用 ;
pc->sz = 0;
pc->capacity = 0;
将有效联系人个数以及最大联系人个数制为 0 ;
退出通讯录 ;
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void menu()
{
printf("*******************************n");
printf("**** 1.add 2.del *****n");
printf("**** 3.search 4.modify *****n");
printf("**** 5.show 6.sort *****n");
printf("**** 0.exit *****n");
printf("*******************************n");
}
enum Option
{
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SHOW,
SORT
};
int main()
{
int input = 0;
struct Contact con;
InitContact(&con);
do {
menu();
printf("请选择->");
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 SHOW:
ShowContact(&con);
break;
case EXIT:
//销毁通讯录
DestroyContact(&con);
printf("退出通讯录n");
break;
default:
printf("选择错误n");
break;
}
} while (input);
return 0;
}
3.2 contact .c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
静态直接开辟存放1000个人信息的版本
//void InitContact(struct Contact* pc)
//{
// pc->sz = 0; //默认没有信息
// memset(pc->date, 0, MAX * sizeof(struct PeoInfo));
// //memset(pc->date, 0, sizeof(pc->date));
//}
//动态开辟的版本
void InitContact(struct Contact* pc)
{
pc->sz = 0;
pc->date = malloc(DEFAULT_SZ * sizeof(struct PeoInfo));
pc->capacity = DEFAULT_SZ; // 3
}
// 静态版本
void Addcontact(struct Contact* pc)
{
struct Contact tmp = { 0 };
if (pc->sz == MAX)
{
printf("通讯录可用空间已满n");
}
else
{
printf("请输入名字:>");
scanf("%s", pc->date[pc->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入性别:>");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入电话:>");
scanf("%s", pc->date[pc->sz].tele);
printf("请输入地址:>");
scanf("%s", pc->date[pc->sz].addr);
printf("添加成功n");
pc->sz++;
}
}
// 动态版本
//void Addcontact(struct Contact* pc)
//{
// 空间满了就扩容
// if (pc->sz == pc->capacity)
// {
// struct PeoInfo* ptr=(struct PeoInfo*)realloc(pc->date, (pc->capacity + 2) * sizeof(struct PeoInfo));
// if (ptr != NULL)
// {
// pc->date = ptr;
// pc->capacity += 2;
// printf("扩容成功n");
// }
// else
// {
// return;
// }
// }
// 录入新增人的信息
// printf("请输入名字:>");
// scanf("%s", pc->date[pc->sz].name);
// printf("请输入年龄:>");
// scanf("%d", &(pc->date[pc->sz].age));
// printf("请输入性别:>");
// scanf("%s", pc->date[pc->sz].sex);
// printf("请输入电话:>");
// scanf("%s", pc->date[pc->sz].tele);
// printf("请输入地址:>");
// scanf("%s", pc->date[pc->sz].addr);
// printf("添加成功n");
// pc->sz++;
//}
void ShowContact(struct Contact* pc)
{
int i = 0;
printf("%15st%5st%8st%15st%30sn",
"name", "age", "sex", "tele", "addr");
for (i = 0; i < pc->sz; i++)
{
//打印每一个数据
printf("%15st%5dt%8st%15st%30sn",
pc->date[i].name,
pc->date[i].age,
pc->date[i].sex,
pc->date[i].tele,
pc->date[i].addr);
}
}
int FindContactByName(const struct Contact* pc, const char* name)
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (strcmp(pc->date[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void DelContact(struct Contact* pc)
{
if (pc->sz == 0)
{
printf("通讯录为空,无法删除n");
return;
}
char name[NAME_MAX] = {0};
printf("请输入要删除人的名字:>");
scanf("%s", name);
// 查找
int pos=FindContactByName(pc, name);
if (pos == -1)
{
printf("指定的联系人不存在n");
}
else
{
// 删除
//将数组中要被删除的元素后面的元素相应向前放
int j = 0;
for (j = pos; jsz-1; j++)
{
pc->date[j] = pc->date[j + 1];
}
pc->sz--;
printf("删除成功n");
}
}
void SearchContact(const struct Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要查找的联系人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("查无此人n");
}
else
{
printf("%15st%5st%8st%15st%30sn",
"name", "age", "sex", "tele", "addr");
printf("%15st%5dt%8st%15st%30sn",
pc->date[pos].name,
pc->date[pos].age,
pc->date[pos].sex,
pc->date[pos].tele,
pc->date[pos].addr);
}
}
void ModifyContact(struct Contact* pc)
{
char name[NAME_MAX] = { 0 };
printf("请输入要修改的联系人的名字:>");
scanf("%s", name);
int pos = FindContactByName(pc, name);
if (pos == -1)
{
printf("要修改的联系人不存在n");
}
else
{
printf("请输入新的名字:>");
scanf("%s", pc->date[pos].name);
printf("请输入新的年龄:>");
scanf("%d", &(pc->date[pos].age));
printf("请输入新的性别:>");
scanf("%s", pc->date[pos].sex);
printf("请输入新的电话:>");
scanf("%s", pc->date[pos].tele);
printf("请输入新的地址:>");
scanf("%s", pc->date[pos].addr);
printf("修改成功n");
}
}
void DestroyContact(struct Contact* pc)
{
free(pc->date);
pc->date = NULL;
pc->sz = 0;
pc->capacity = 0;
}
3.3 contact.h
#pragma once #define DEFAULT_SZ 3 #define NAME_MAX 30 #define SEX_MAX 5 #define TELE_MAX 12 #define ADDR_MAX 30 #define MAX 1000 #include4.尾声#include #include #include struct PeoInfo { char name[NAME_MAX]; int age; char sex[SEX_MAX]; char tele[TELE_MAX]; char addr[ADDR_MAX]; }; // 静态通讯录版本 //struct Contact //{ // struct PeoInfo date[MAX]; // int sz; //}; //动态通讯录版本 struct Contact { struct PeoInfo* date; int sz; int capacity; }; // 初始化通讯录 void InitContact(struct Contact* pc); //增加人的信息 void Addcontact(struct Contact* pc); //显示联系人 void ShowContact(struct Contact*pc); //删除指定联系人 void DelContact(struct Contact* pc); //查找指定联系人 void SearchContact(struct Contact* pc); //修改指定联系人 void ModifyContact(struct Contact* pc); //销毁通讯录 void DestroyContact(struct Contact* pc);
写到这里,关于静态通讯录和动态通讯录的讲解就已经完成,如果觉得文章对自己有所帮助,欢迎大家多多点赞收藏评论,这对博主来说是莫大的鼓励~谢谢各位啦 ~~



