目录
前言
通讯录数据结构
通讯录初始化
查找名字
增加联系人
删除联系人
展示所有联系人
查找联系人
修改信息
销毁通讯录
完整通讯录代码
前言
数据结构中的顺序表如果已经学会了,那么我们就可以基于顺序表来完成一个通讯录了
通讯录其实我们使用前面学习过的顺序表就能完成不过,相比较来说,前面的顺序表就是个整型数组,但通讯录就是一个多信息的自定义类型了
如果没了解过顺序表的可以看看我前篇博客
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;
}
完