目录
Contact.h说明:
概述:为了实现这个小项目,我开创了一个头文件:Contact.h .和两个源文件:Contact.c,ConTest.c,在Contact.h中进行结构体的声明,函数的声明和头文件的包含。Contact.c文件主要用于各个函数的实现,而ConTest则用于测试函数。
结构体与头文件的包含: ![](https://i-blog.csdnimg.cn/blog_migrate/6b1a971bc06fdf0b209e25c9f5f95a39.png)
这里通过结构体数组来进行数据的插入与删除操作,为了后续的书写方便,将各个结构体变量的名字重新定义为其缩写形式(底层原理是顺序表)
函数在头文件的声明与定义:
void SLCheckCapacity(Contact* pocn);//用于顺序表的扩容
void SLPushBack(Contact* ps, ConDataType x);//顺序表的尾插
void SLErase(Contact* ps, int pos);//顺序表的删除
int FindByName(Contact* pocn, char name[]);//查找名字是否匹配
void ContactInit(Contact* pocn);//通讯录的初始化
void ContactDestory(Contact* pocn);//通讯录的摧毁
void ContactAdd(Contact* pocn);//通讯录的增加联系人
void ContactDel(Contact* pocn);//通讯录的删除联系人
void ContactModify(Contact* pocn);//通讯录的修改联系人信息
void ContactFind(Contact* pocn);//通讯录的查找
void ContactShow(Contact* pocn);//当前通讯录的信息的展示
Contact.c中各个函数的实现:
1.检查链表中的数据是否满了,满了就扩容
代码详解:
//检查链表中的数据是否满了,满了就扩容
void SLCheckCapacity(Contact* pocn) {
if (pocn->size == pocn->capacity) {
int newCapacity = pocn->capacity == 0 ? 4 : 2 * pocn->capacity;//这里通过realloc来申请空间
ConDataType* tmp = (ConDataType*)realloc(pocn->arr, newCapacity * sizeof(ConDataType));
if (tmp == NULL) {
perror("realloc fail!");
exit(1);
}
//扩容成功
pocn->arr = tmp;//注意要将当前的指针指向开创好的空间
pocn->capacity = newCapacity;//容量也不要遗漏
}
}
由于顺序表是由数组实现的,如果定义一个静态数组,很不利于数据的存储。定义得太大浪费空间,定义得太小空间不够,这里我选择使用动态链表的形式实现这个问题,所以这里定义了一个函数SLCheckCapacity来检查链表的大小(size)是否超过其最大容量(capacity)。如果超过了,就需要进行扩容操作。没有就不需要进行任何操作。同时,为了和里这里扩容两倍。
2.链表的尾插
代码详解:
//链表的尾插
void SLPushBack(Contact* ps, ConDataType x) {
assert(ps);
SLCheckCapacity(ps);
ps->arr[ps->size++] = x;
}
首先判断这里的结构体指针是否为空,简单粗暴的方法:断言(assert),注意要引用头文件#include<assert.h>。接着要检查顺序表的容量是否满了,如果满了就扩容。 接着将数据插入尾部。
3.链表的删除
代码解释:
//链表的删除
void SLErase(Contact* ps, int pos) {
assert(ps);
assert(pos >= 0 && pos < ps->size);
//pos以后的数据往前挪动一位
for (int i = pos; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];//ps->arr[i-2] = ps->arr[i-1];
}
ps->size--;
}
4.查找名字是否匹配
代码解释:
//查找名字是否匹配
int FindByName(Contact* pocn, char name[]) {
for (int i = 0; i < pocn->size; i++) {
if (strcmp(pocn->arr[i].name, name) == 0) {
return i;
}
}
return -1;
}
如果有遗忘strcmp的小伙伴记得查收~
strcmp比较两个字符串的大小,一个字符一个字符比较,按ASCLL码比较
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
5.初始化通讯录
代码解释:
//初始化通讯录
void ContactInit(Contact* pocn) {
pocn->arr = NULL;
pocn->capacity = pocn->size = 0;
}
6. 通讯录的摧毁
代码解释:
//通讯录的摧毁
void ContactDestory(Contact* pocn) {
assert(pocn);
if (pocn->arr) {
free(pocn->arr);
}
pocn->arr = NULL;
pocn->capacity = pocn->size = 0;
}
7.添加联系人的信息
代码解释:
//添加联系人的信息
void ContactAdd(Contact* pocn) {
Info info;
//输入各个联系人的信息
printf("请输入联系人姓名:\n");
scanf("%s", info.name);
printf("请输入联系人年龄:\n");
scanf("%d", &info.age);
printf("请输入联系人性别:\n");
scanf("%s", info.gender);
printf("请输入联系人电话:\n");
scanf("%s", info.tel);
printf("请输入联系人地址:\n");
scanf("%s", info.addr);
//用尾插法进行数据的增添
SLPushBack(pocn, info);
}
输入联系人的各个信息后将其尾插到链表后
8.删除联系人的信息
代码解释:
//删除联系人的信息
void ContactDel(Contact* pocn) {
//删除之前要先查找
//找到之后可以删除找不到,就不能进行删除操作
printf("请输入要删除的联系人名字:\n");
char name[NAME_MAX];
scanf("%s", name);
//定义findIndex来判断是否存在联系人信息
int findIndex = FindByName(pocn, name);
if (findIndex < 0) {
printf("要删除的信息不存在!\n");
return;
}
//存在就删除
SLErase(pocn, findIndex);
printf("联系人删除成功!\n");
}
9.修改联系人信息
代码解释:
//修改联系人信息
void ContactModify(Contact* pocn) {
//修改之前先查找
//如果没有找到,就无法进行修改操作
char name[NAME_MAX];
printf("请输入要修改的联系人姓名:\n");
scanf("%s", name);
int findIndex = FindByName(pocn, name);
if (findIndex < 0) {
printf("要修改的联系人找不到!\n");
return;
}
//修改后输入新的联系人的信息
printf("请输入姓名:\n");
scanf("%s", pocn->arr[findIndex].name);
printf("请输入年龄:\n");
scanf("%d", &pocn->arr[findIndex].age);
printf("请输入性别:\n");
scanf("%s", pocn->arr[findIndex].gender);
printf("请输入电话:\n");
scanf("%s", pocn->arr[findIndex].tel);
printf("请输入地址:\n");
scanf("%s", pocn->arr[findIndex].addr);
printf("联系人修改成功!\n");
}
10.查找联系人
代码解释:
//查找联系人
void ContactFind(Contact* pocn) {
printf("请输入要查找的联系人姓名:\n");
char name[NAME_MAX];
scanf("%s", name);
int findIndex = FindByName(pocn, name);
if (findIndex < 0) {
printf("找不到该联系人,联系人不存在!\n");
return;
}
else printf("找到了,输出对应信息:\n");
printf("%s %s %s %s %s\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%s %d %s %s %s\n",
pocn->arr[findIndex].name,
pocn->arr[findIndex].age,
pocn->arr[findIndex].gender,
pocn->arr[findIndex].tel,
pocn->arr[findIndex].addr
);
}
11.通讯录当前的联系人展示
代码解释:
//通讯录当前的联系人展示
void ContactShow(Contact* pocn) {
printf("%s %s %s %s %s\n", "姓名", "年龄", "性别", "电话", "地址");
for (int i = 0; i < pocn->size; i++) {
printf("%s %d %s %s %s\n",
pocn->arr[i].name,
pocn->arr[i].age,
pocn->arr[i].gender,
pocn->arr[i].tel,
pocn->arr[i].addr
);
}
}
ConTest.c源文件:
代码详解:
//引入头文件
#include"Contact.h"
void menu()//菜单的打印
{
printf("-------------------------请输入--------------------------------\n");
printf("----------------1.增加联系人 2.删除联系人---------------------\n");
printf("---------------3.修改联系人 4.查找联系人---------------------\n");
printf("---------------5.查看通讯录 0.退出通讯录---------------------\n");
printf("---------------------------------------------------------------\n");
}
int main()
{
int op = -1;
Contact con;
ContactInit(&con);
do {
menu();
printf("请选择操作:");
scanf("%d", &op);//这里按照菜单的指示来选择操作
switch (op) {//各个数字对应各个的操作
case 1:
ContactAdd(&con);
break;
case 2:
ContactDel(&con);
break;
case 3:
ContactModify(&con);
break;
case 4:
ContactFind(&con);
break;
case 5:
ContactShow(&con);
break;
case 0:
printf("通讯录退出中……\n");
break;
default :
break;
}
} while (op != 0);
ContactDestory(&con);//注意结束时要摧毁通讯录,防止内存泄漏
return 0;
}
在ConTest文件中,主要是实现菜单的打印与各个函数操作的选择
测试数据:
最后完整代码展示:
Contact.h:
#include<assert.h>
#include<stdlib.h>
//为了后续方便,这里将所要用到的数组的数据都重新定义
#define NAME_MAX 100
#define GENDER_MAX 10
#define TEL_MAX 12
#define ADDR_MAX 100
//联系人信息的存储(用结构体实现)
typedef struct PresonInformation
{
char name[NAME_MAX];
int age;
char gender[GENDER_MAX];
char tel[TEL_MAX];
char addr[ADDR_MAX];
}Info;
typedef Info ConDataType;
//对链表的声明与定义(结构体数组),用于对上述结构体信息存储
typedef struct SeqList
{
ConDataType* arr;
int capacity;
int size;
}Contact;
void SLCheckCapacity(Contact* pocn);//用于顺序表的扩容
void SLPushBack(Contact* ps, ConDataType x);//顺序表的尾插
void SLErase(Contact* ps, int pos);//顺序表的删除
int FindByName(Contact* pocn, char name[]);//查找名字是否匹配
void ContactInit(Contact* pocn);//通讯录的初始化
void ContactDestory(Contact* pocn);//通讯录的摧毁
void ContactAdd(Contact* pocn);//通讯录的增加联系人
void ContactDel(Contact* pocn);//通讯录的删除联系人
void ContactModify(Contact* pocn);//通讯录的修改联系人信息
void ContactFind(Contact* pocn);//通讯录的查找
void ContactShow(Contact* pocn);//当前通讯录的信息的展示
Contact.c:
#include"Contact.h"
//检查链表中的数据是否满了,满了就扩容
void SLCheckCapacity(Contact* pocn) {
if (pocn->size == pocn->capacity) {
int newCapacity = pocn->capacity == 0 ? 4 : 2 * pocn->capacity;//这里通过realloc来申请空间
ConDataType* tmp = (ConDataType*)realloc(pocn->arr, newCapacity * sizeof(ConDataType));
if (tmp == NULL) {
perror("realloc fail!");
exit(1);
}
//扩容成功
pocn->arr = tmp;//注意要将当前的指针指向开创好的空间
pocn->capacity = newCapacity;//容量也不要遗漏
}
}
//链表的尾插
void SLPushBack(Contact* ps, ConDataType x) {
assert(ps);
SLCheckCapacity(ps);
ps->arr[ps->size++] = x;
}
//链表的删除
void SLErase(Contact* ps, int pos) {
assert(ps);
assert(pos >= 0 && pos < ps->size);
//pos以后的数据往前挪动一位
for (int i = pos; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];//ps->arr[i-2] = ps->arr[i-1];
}
ps->size--;
}
//查找名字是否匹配
int FindByName(Contact* pocn, char name[]) {
for (int i = 0; i < pocn->size; i++) {
if (strcmp(pocn->arr[i].name, name) == 0) {
return i;
}
}
return -1;
}
//初始化通讯录
void ContactInit(Contact* pocn) {
pocn->arr = NULL;
pocn->capacity = pocn->size = 0;
}
//通讯录的摧毁
void ContactDestory(Contact* pocn) {
assert(pocn);
if (pocn->arr) {
free(pocn->arr);
}
pocn->arr = NULL;
pocn->capacity = pocn->size = 0;
}
//添加联系人的信息
void ContactAdd(Contact* pocn) {
Info info;
//输入各个联系人的信息
printf("请输入联系人姓名:\n");
scanf("%s", info.name);
printf("请输入联系人年龄:\n");
scanf("%d", &info.age);
printf("请输入联系人性别:\n");
scanf("%s", info.gender);
printf("请输入联系人电话:\n");
scanf("%s", info.tel);
printf("请输入联系人地址:\n");
scanf("%s", info.addr);
//用尾插法进行数据的增添
SLPushBack(pocn, info);
}
//删除联系人的信息
void ContactDel(Contact* pocn) {
//删除之前要先查找
//找到之后可以删除找不到,就不能进行删除操作
printf("请输入要删除的联系人名字:\n");
char name[NAME_MAX];
scanf("%s", name);
//定义findIndex来判断是否存在联系人信息
int findIndex = FindByName(pocn, name);
if (findIndex < 0) {
printf("要删除的信息不存在!\n");
return;
}
//存在就删除
SLErase(pocn, findIndex);
printf("联系人删除成功!\n");
}
//修改联系人信息
void ContactModify(Contact* pocn) {
//修改之前先查找
//如果没有找到,就无法进行修改操作
char name[NAME_MAX];
printf("请输入要修改的联系人姓名:\n");
scanf("%s", name);
int findIndex = FindByName(pocn, name);
if (findIndex < 0) {
printf("要修改的联系人找不到!\n");
return;
}
//修改后输入新的联系人的信息
printf("请输入姓名:\n");
scanf("%s", pocn->arr[findIndex].name);
printf("请输入年龄:\n");
scanf("%d", &pocn->arr[findIndex].age);
printf("请输入性别:\n");
scanf("%s", pocn->arr[findIndex].gender);
printf("请输入电话:\n");
scanf("%s", pocn->arr[findIndex].tel);
printf("请输入地址:\n");
scanf("%s", pocn->arr[findIndex].addr);
printf("联系人修改成功!\n");
}
//查找联系人
void ContactFind(Contact* pocn) {
printf("请输入要查找的联系人姓名:\n");
char name[NAME_MAX];
scanf("%s", name);
int findIndex = FindByName(pocn, name);
if (findIndex < 0) {
printf("找不到该联系人,联系人不存在!\n");
return;
}
else printf("找到了,输出对应信息:\n");
printf("%s %s %s %s %s\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%s %d %s %s %s\n",
pocn->arr[findIndex].name,
pocn->arr[findIndex].age,
pocn->arr[findIndex].gender,
pocn->arr[findIndex].tel,
pocn->arr[findIndex].addr
);
}
//通讯录当前的联系人展示
void ContactShow(Contact* pocn) {
printf("%s %s %s %s %s\n", "姓名", "年龄", "性别", "电话", "地址");
for (int i = 0; i < pocn->size; i++) {
printf("%s %d %s %s %s\n",
pocn->arr[i].name,
pocn->arr[i].age,
pocn->arr[i].gender,
pocn->arr[i].tel,
pocn->arr[i].addr
);
}
}
ConTest.c:
//引入头文件
#include"Contact.h"
void menu()//菜单的打印
{
printf("-------------------------请输入--------------------------------\n");
printf("----------------1.增加联系人 2.删除联系人---------------------\n");
printf("---------------3.修改联系人 4.查找联系人---------------------\n");
printf("---------------5.查看通讯录 0.退出通讯录---------------------\n");
printf("---------------------------------------------------------------\n");
}
int main()
{
int op = -1;
Contact con;
ContactInit(&con);
do {
menu();
printf("请选择操作:");
scanf("%d", &op);//这里按照菜单的指示来选择操作
switch (op) {//各个数字对应各个的操作
case 1:
ContactAdd(&con);
break;
case 2:
ContactDel(&con);
break;
case 3:
ContactModify(&con);
break;
case 4:
ContactFind(&con);
break;
case 5:
ContactShow(&con);
break;
case 0:
printf("通讯录退出中……\n");
break;
default :
break;
}
} while (op != 0);
ContactDestory(&con);//注意结束时要摧毁通讯录,防止内存泄漏
return 0;
}
博客到这里也是结束了,制作不易,喜欢的小伙伴可以点赞加关注支持下博主,这对我真的很重要~~