目录
前言
通讯录数据结构
通讯录初始化
查找名字
增加联系人
删除联系人
展示所有联系人
查找联系人
修改信息
销毁通讯录
完整通讯录代码
前言
数据结构中的顺序表如果已经学会了,那么我们就可以基于顺序表来完成一个通讯录了
通讯录其实我们使用前面学习过的顺序表就能完成不过,相比较来说,前面的顺序表就是个整型数组,但通讯录就是一个多信息的自定义类型了
如果没了解过顺序表的可以看看我前篇博客
C数据结构:顺序表-CSDN博客
下面直接来开始完成我们的通讯录吧
通讯录数据结构
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
typedef PeoInfo SLDataType;
//typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;
int size; // 有效数据个数
int capacity; // 空间容量
}SL;
通讯里结构体里定义了五个成员,名字、性别、年龄、电话、地址
数组大小使用了宏定义,因为有需要更改的时候就比较方便,不需要一个个去更改
下面就开始通讯录的实现吧
如果文件中有顺序表的.c文件,请务必屏蔽以下函数,否则会引起报错
1. SLPrint函数中含有 %d,%d是整型的占位符,如果我们需要打印自定义类型是不能使用%d占位符的
2. SLFind函数中if的判断条件 ps->a[i] == x这个有错误,我们的a数组的类型是个自定义类型,该类型里含有5个成员,怎么能直接让两个自定义类型直接比较呢?
通讯录初始化
void InitContact(contact* con)
{
SLInit(con);
}
初始化一个联系人就和初始化一个顺序表一样,所以直接使用顺序表的函数对里面的参数con进行初始化即可
查找名字
int FindByName(contact* con, char name[])
{
assert(con);
for (int i = 0; i < con->size; i++)
{
if (strcmp(con->a[i].name, name) == 0)
{
return i;
}
}
return -1;
}
为什么要先写查找名字呢?
因为我们后面删除联系人、查找联系人、修改联系人都会使用到这个模板,如果都按一个模板来写会显得代码很冗余,并且浪费时间,所以我们直接写一个函数就可以有效的解决这个问题
我们直接遍历整个联系人a数组里面的名字,当名字匹配的时候,我们就返回它的下标,否则出了循环之后说明没找到名字,则返回-1
我们不能直接写
con->a[i].name == name作为if语句的条件
因为这个name是个char类型的数组名,而数组名是地址,用地址来比较是得不出答案的,所以需要借助到string.h里的strcmp函数
对string.h库函数有兴趣的可以看看我前面的博客
ctype.h的了解string.h库函数中各个函数的使用和模拟实现-CSDN博客
增加联系人
void AddContact(contact* con)
{
assert(con);
PeoInfo c;
printf("请输入姓名:>");
scanf("%s", c.name);
printf("请输入性别:>");
scanf("%s", c.sex);
printf("请输入年龄:>");
scanf("%d", &c.age);
printf("请输入电话:>");
scanf("%s", c.tel);
printf("请输入地址:>");
scanf("%s", c.addr);
SLPushBack(con, c);
}
void SLPushBack(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps); //检查数组大小是否足够
ps->a[ps->size] = x;
ps->size++;
}
先是定义了一个通讯录c变量,并把我们需要增加的联系人的信息先暂时放到c中
最后使用顺序表里的SLPushBack函数将这些信息放到我们的通讯录数组中即可
删除联系人
void DelContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("请输入要删除的姓名:>");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0)
{
printf("要删除的用户不存在!\n");
return;
}
SLErase(con, pos);
printf("删除成功\n");
}
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos <= ps->size && pos >= 0);
assert(ps->size > 0);
for (int i = pos; i < ps->size - 1; i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
先定义了一个name数组接收我们要删除的人的名字,然后使用我们前面写到的FindByName找到这个名字的下标,最后使用SLErase函数删除掉通讯录数组这个下标所在的位置即可
展示所有联系人
void ShowContact(contact* con)
{
assert(con);
//打印表头
printf("姓名\t性别\t年龄\t电话\t地址\n");
for (int i = 0; i < con->size; i++)
{
printf("%s\t%s\t%d\t%s\t%s\n", con->a[i].name,
con->a[i].sex,
con->a[i].age,
con->a[i].tel,
con->a[i].addr
);
}
}
展示这一步就是给使用者看的,为了美观对齐所以在每一个信息的后面加了一个\t
最后用for循环遍历通讯录数组打印所有的信息即可
查找联系人
void FindContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("请输入要查找的姓名:>");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0)
{
printf("查找的用户不存在!\n");
return;
}
printf("查找成功\n");
printf("%s\t%s\t%d\t%s\t%s\t", con->a[pos].name,
con->a[pos].sex,
con->a[pos].age,
con->a[pos].tel,
con->a[pos].addr
);
}
还是一样先找到名字所在通讯录数组的下标,如果能找到说明联系人存在,利用下标打印出该人的信息即可
修改信息
void ModifyContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("请输入要修改的姓名:>");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0)
{
printf("查找的用户不存在!\n");
return;
}
printf("请输入姓名:>");
scanf("%s", con->a[pos].name);
printf("请输入性别:>");
scanf("%s", con->a[pos].sex);
printf("请输入年龄:>");
scanf("%d", &con->a[pos].age);
printf("请输入电话:>");
scanf("%s", con->a[pos].tel);
printf("请输入地址:>");
scanf("%s", con->a[pos].addr);
printf("修改成功\n");
}
也是一样先查找该名字所在通讯录数组的下标,然后重新使用scanf输入该下标的所有信息即可
销毁通讯录
void DestroyContact(contact* con)
{
assert(con);
SLDestroy(con);
}
void SLDestroy(SL* ps)
{
assert(ps);
if (ps->a)
{
free(ps->a);
}
ps->a = NULL;
ps->capacity = ps->size = 0;
}
销毁直接用顺序表中的SLDestroy实现即可
完整通讯录代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100
//前置声明
typedef struct SeqList contact;
//用户数据
typedef struct PersonInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}PeoInfo;
//初始化通讯录
void InitContact(contact* con);
//添加通讯录数据
void AddContact(contact* con);
//删除通讯录数据
void DelContact(contact* con);
//展示通讯录数据
void ShowContact(contact* con);
//查找通讯录数据
void FindContact(contact* con);
//修改通讯录数据
void ModifyContact(contact* con);
//销毁通讯录数据
void DestroyContact(contact* con);
typedef PeoInfo SLDataType;
//typedef int SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{
SLDataType* a;
int size; // 有效数据个数
int capacity; // 空间容量
}SL;
//初始化和销毁
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
//扩容
void SLCheckCapacity(SL* ps);
//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);
//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);
int SLFind(SL* ps, SLDataType x);
void SLInit(SL* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = ps->size = 0;
}
void SLDestroy(SL* ps)
{
assert(ps);
if (ps->a)
{
free(ps->a);
}
ps->a = NULL;
ps->capacity = ps->size = 0;
}
//void SLPrint(SL* ps)
//{
// assert(ps);
//
// for (int i = 0; i < ps->size; i++)
// {
// printf("%d ", ps->a[i]);
// }
// printf("\n");
//}
void SLCheckCapacity(SL* ps)
{
assert(ps);
if (ps->capacity == 0)
{
ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);
ps->capacity = 4;
}
if (ps->capacity == ps->size && ps->capacity != 0)
{
//定义tmp接收防止扩容失败原数组被覆盖
SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc fail!\n");
return;
}
//扩容成功
ps->a = tmp;
ps->capacity *= 2;
}
}
void SLPushBack(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
void SLPopBack(SL* ps)
{
assert(ps);
assert(ps->size > 0);
ps->size--;
}
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
for (int i = ps->size - 1; i >= 0; i--)
{
ps->a[i + 1] = ps->a[i];
}
ps->a[0] = x;
ps->size++;
}
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size > 0);
for (int i = 0; i < ps->size - 1; i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos <= ps->size && pos >= 0);
SLCheckCapacity(ps);
for (int i = ps->size; i >= pos; i--)
{
ps->a[i + 1] = ps->a[i];
}
ps->a[pos] = x;
ps->size++;
}
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos <= ps->size && pos >= 0);
assert(ps->size > 0);
for (int i = pos; i < ps->size - 1; i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
//int SLFind(SL* ps, SLDataType x)
//{
// assert(ps);
//
// for (int i = 0; i < ps->size; i++)
// {
// if (ps->a[i] == x)
// {
// return i;
// }
// }
//
// return -1;
//}
void InitContact(contact* con)
{
SLInit(con);
}
void AddContact(contact* con)
{
assert(con);
PeoInfo c;
printf("请输入姓名:>");
scanf("%s", c.name);
printf("请输入性别:>");
scanf("%s", c.sex);
printf("请输入年龄:>");
scanf("%d", &c.age);
printf("请输入电话:>");
scanf("%s", c.tel);
printf("请输入地址:>");
scanf("%s", c.addr);
SLPushBack(con, c);
}
int FindByName(contact* con, char name[])
{
assert(con);
for (int i = 0; i < con->size; i++)
{
if (strcmp(con->a[i].name, name) == 0)
{
return i;
}
}
return -1;
}
void DelContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("请输入要删除的姓名:>");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0)
{
printf("要删除的用户不存在!\n");
return;
}
SLErase(con, pos);
printf("删除成功\n");
}
void ShowContact(contact* con)
{
assert(con);
//打印表头
printf("姓名\t性别\t年龄\t电话\t地址\n");
for (int i = 0; i < con->size; i++)
{
printf("%s\t%s\t%d\t%s\t%s\n", con->a[i].name,
con->a[i].sex,
con->a[i].age,
con->a[i].tel,
con->a[i].addr
);
}
}
void FindContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("请输入要查找的姓名:>");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0)
{
printf("查找的用户不存在!\n");
return;
}
printf("查找成功\n");
printf("%s\t%s\t%d\t%s\t%s\t", con->a[pos].name,
con->a[pos].sex,
con->a[pos].age,
con->a[pos].tel,
con->a[pos].addr
);
}
void ModifyContact(contact* con)
{
assert(con);
char name[NAME_MAX];
printf("请输入要修改的姓名:>");
scanf("%s", name);
int pos = FindByName(con, name);
if (pos < 0)
{
printf("查找的用户不存在!\n");
return;
}
printf("请输入姓名:>");
scanf("%s", con->a[pos].name);
printf("请输入性别:>");
scanf("%s", con->a[pos].sex);
printf("请输入年龄:>");
scanf("%d", &con->a[pos].age);
printf("请输入电话:>");
scanf("%s", con->a[pos].tel);
printf("请输入地址:>");
scanf("%s", con->a[pos].addr);
printf("修改成功\n");
}
void DestroyContact(contact* con)
{
assert(con);
SLDestroy(con);
}
void Test2()
{
contact c;
InitContact(&c);
AddContact(&c);
AddContact(&c);
ShowContact(&c);
//DelContact(&c);
ModifyContact(&c);
ShowContact(&c);
FindContact(&c);
DestroyContact(&c);
}
int main()
{
//Test1();
Test2();
return 0;
}
完