1. 基于动态顺序表实现通讯录
动态顺序表:https://blog.csdn.net/YUYUJOB/article/details/136688509
C语言基础要求:结构体、动态内存管理、顺序表、文件操作
功能要求:
1)至少能够存储100个人的通讯信息
2)能够保存用户信息:名字、性别、年龄、电话、地址等
3)增加联系人信息
4)删除指定联系人
5)查找制定联系人
6)修改指定联系人
7)显示联系人信息
通讯录本质将一个通讯录结构体类型的变量存放在指针数组内
Contact.h --文件
#define NAME_MAX 100
#define SEX_MAX 10
#define TEL_MAX 15
#define ADDR_MAX 100
typedef struct ContactInfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}CInfo;
//这样重新命名方便有辨识度
typedef struct SeqList contact;
//通讯录初始化与销毁
void ContactInit(contact* pcon); //等价于(SL* pcon),讲究代码的一致性
void ContactDestroy(contact* pcon);
//添加联系人
void ContactAdd(contact* pcon);
//删除联系人
void ContactDel(contact* pcon);
//修改联系人
void ContactModify(contact* pcon);
//查看联系人
void Contactshow(contact* pcon);
//查找联系人
void ContactFind(contact* pcon);
SeqList.h --文件
typedef struct ContactInfo SLDataType; //自定义一个可随时改变存储类型的类型名
typedef struct SeqList
{
SLDataType* a;
int size; //顺序表内的有效个数
int capacity; //顺序表的空间大小
}SL;
//对顺序表进行初始化
void SLInit(SL* ps);
//进行顺序表进行销毁
void SLDestroy(SL* ps);
//尾部插入
void SLPushBack(SL* ps, SLDataType x);
//任意位置删除
void SLErase(SL* ps, int pos);
//
bool SLIsEmpty(SL* ps);
SeqList.c --文件
#include"SeqList.h"
//初始化
void SLInit(SL* ps) {
ps->a = NULL;
ps->size = ps->capacity = 0;
}
//销毁
void SLDestroy(SL* ps) {
if (ps->a)
free(ps->a);
//防止变为野指针
ps->a = NULL;
ps->size = ps->capacity = 0;
}
//是否需要开辟新的空间
void SLCheckCapacity(SL* ps) {
//判断此时的空间是否充足
if (ps->size == ps->capacity) {
//判断初始值的Capacity是否为0,毕竟0二倍还是0
int newCapatity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
//空间不足则需要扩容 (一般情况都以1.5/2倍扩容)
SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapatity * sizeof(SLDataType));
//realloc 也存在申请失败
if (tmp == NULL) {
perror("realloc fail!\n");
return 1;
}
ps->a = tmp;
ps->capacity = newCapatity;
}
}
// 尾插
void SLPushBack(SL* ps, SLDataType x) {
//判断是否为空指针
assert(ps);
//判断此时的空间是否充足
SLCheckCapacity(ps);
//size也需要++,下列直接简便式
ps->a[ps->size++] = x;
}
//头插
void SLPushFront(SL* ps, SLDataType x) {
assert(ps);
//判断是否空间足够,不够则扩容
SLCheckCapacity(ps);
//头部插入数据,历史数据后移一位
for (size_t i = ps->size; i > 0; i--) {
ps->a[i] = ps->a[i - 1];
}
ps->a[0] = x;
ps->size++;
}
//尾删
void SLPopback(SL* ps) {
assert(!SLIsEmpty(ps));//等价于 assert(ps->size) 如果size为假,则断言
assert(ps);
ps->size--;
}
//任意位置插入
void SLInsert(SL* ps, int pos, SLDataType x) {
assert(ps);
assert(pos >= 0 && pos <= ps->size);
//判断是否空间足够,不够则扩容
SLCheckCapacity(ps);
for (size_t i = ps->size; i > pos; i--) {
ps->a[i] = ps->a[i - 1];
}
ps->a[pos] = x;
ps->size++;
}
//任意位置删除
void SLErase(SL* ps, int pos) {
assert(ps);
assert(!SLIsEmpty(ps));
assert(pos >= 0 && pos < ps->size);
for (size_t i = pos; i < ps->size - 1; i++) {
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
bool SLIsEmpty(SL* ps) {
assert(ps);
//这样是不对的,这样只能判断空间是否足够
//return ps->szie == ps->capacity
return ps->size == 0;
}
Contact.c --文件
#include"Contact.h"
#include"SeqList.h"
//通讯录的初始化
void ContactInit(contact* pcon) {
SLInit(pcon);
}
//通讯录的销毁
void ContactDestroy(contact* pcon) {
SLDestroy(pcon);
}
//通讯录中添加联系人
void ContactAdd(contact* pcon) {
CInfo info;
printf("请输入联系人姓名:\n");
scanf("%s", info.name);
printf("请输入联系人性别:\n");
scanf("%s", info.sex);
printf("请输入联系人年龄:\n");
scanf("%d", &info.age);
printf("请输入联系人电话:\n");
scanf("%s", info.tel);
printf("请输入联系人地址:\n");
scanf("%s", info.addr);
//联系人数据添加到SL结构类型的a首地址去
SLPushBack(pcon, info);
}
//查找通讯录联系人
int FindByName(contact* pcon,char name[]){
for (int i = 0; i < pcon->size; i++) {
if (strcmp(pcon->a[i].name, name) == 0) {
return i;
}
}
return -1;
}
//删除通讯录联系人
void ContactDel(contact* pcon) {
printf("请输入要删除的联系人姓名:\n");
char name[NAME_MAX];
scanf("%s", name);
int findidex = FindByName(pcon, name);
//不存在的情况
if (findidex < 0) {
printf("所要删除的联系人不存在!\n");
return;
}
SLErase(pcon, findidex);
}
//修改通讯录联系人
void ContactModify(contact* pcon) {
printf("请输入要修改的用户名称:\n");
char name[NAME_MAX];
scanf("%s", name);
int findidex = FindByName(pcon, name);
if (findidex < 0) {
printf("要修改的用户不存在!\n");
return;
}
//以下进行修改
printf("请输入联系人姓名:\n");
scanf("%s", pcon->a[findidex].name);
printf("请输入联系人性别:\n");
scanf("%s", pcon->a[findidex].sex);
printf("请输入联系人年龄:\n");
scanf("%d", &pcon->a[findidex].age);
printf("请输入联系人电话:\n");
scanf("%s", pcon->a[findidex].tel);
printf("请输入联系人地址:\n");
scanf("%s", pcon->a[findidex].addr);
printf("修改成功!");
}
//查看通讯录联系人
void Contactshow(contact* pcon) {
//也就是打印通讯录里的信息
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < pcon->size; i++) {
printf("%-4s %-4s %-4d %-4s %-4s\n",
pcon->a[i].name,
pcon->a[i].sex,
pcon->a[i].age,
pcon->a[i].tel,
pcon->a[i].addr
);
}
}
//查找通讯录指定联系人
void ContactFind(contact* pcon) {
char name[NAME_MAX];
printf("请输入查找联系人姓名:\n");
scanf("%s", name);
int findidex = FindByName(pcon, name);
if (findidex < 0) {
printf("查找的用户不存在!");
return;
}
printf("%s %s %s %s %s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-4s %-4s %-4d %-4s %-4s\n",
pcon->a[findidex].name,
pcon->a[findidex].sex,
pcon->a[findidex].age,
pcon->a[findidex].tel,
pcon->a[findidex].addr
);
}
SeqList.c --文件
#include"SeqList.h"
void SLInit(SL* ps) {
ps->a = NULL;
ps->size = ps->capacity = 0;
}
void SLDestroy(SL* ps) {
if (ps->a)
free(ps->a);
//防止变为野指针
ps->a = NULL;
ps->size = ps->capacity = 0;
}
void SLCheckCapacity(SL* ps) {
//判断此时的空间是否充足
if (ps->size == ps->capacity) {
//判断初始值的Capacity是否为0,毕竟0二倍还是0
int newCapatity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
//空间不足则需要扩容 (一般情况都以1.5/2倍扩容)
SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapatity * sizeof(SLDataType));
//realloc 也存在申请失败
if (tmp == NULL) {
perror("realloc fail!\n");
return 1;
}
ps->a = tmp;
ps->capacity = newCapatity;
}
}
// 尾插
void SLPushBack(SL* ps, SLDataType x) {
//判断是否为空指针
assert(ps);
//判断此时的空间是否充足
SLCheckCapacity(ps);
//size也需要++,下列直接简便式
ps->a[ps->size++] = x;
}
//任意位置删除
void SLErase(SL* ps, int pos) {
assert(ps);
assert(!SLIsEmpty(ps)); //等价于ps->size != 0
assert(pos >= 0 && pos < ps->size);
for (size_t i = pos; i < ps->size - 1; i++) {
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
bool SLIsEmpty(SL* ps) {
assert(ps);
//这样是不对的,这样只能判断空间是否足够
//return ps->szie == ps->capacity ----错误
return ps->size == 0;
}
test.c --文件
#include"SeqList.h"
#include"Contact.h"
void menu() {
printf(" ************* 通讯录 *********************\n");
printf("************1、添加 2、删除 3、修改 *************\n");
printf("************4、查找 5、查看 0、退出 *************\n");
printf(" ********************************************\n");
}
int main()
{
int op = -1;
contact con;
ContactInit(&con);
do {
menu();
printf("请选择你的操作:\n");
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("goodbye!\n");
break;
default:
printf("输入有误请在菜单里选择!");
break;
}
} while (op != 0);
return 0;
}
ok,今天的分享就到这里啦,欢迎你的莅临,也非常希望你宝贵的建议,让我们一起进步!
您的三连就是对yuyu在编程路上最强的动力!