1.功能实现
功能要求
1)至少能够存储100个人的通讯信息
2)能够保存用户信息:名字、性别、年龄、电话、地址等
3)增加联系人信息
4)删除指定联系人
5)查找制定联系人
6)修改指定联系人
7)显联系人信息
2.与顺序表的关系
3.代码实现
1.通讯录基本结构Contact.h
Contact.h
文件代码如下
#define _CRT_SECURE_NO_WARNINGS 1
#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;
//此处相当于把顺序表的名字改为通讯录,也可以理解为我把顺序表的SL改为了contact,不容易搞混
//因为并没有调用"SeqList.h"里面的数据或者函数,所以这里不需要调用
void ContactInit(contact* 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); //查找联系人
2.基于通讯录SqList.h
文件的改进
需要把顺序表的数据类型改为通讯录的结构体,这里就体现了之前在顺序表把
int
类型通过typedef
声明为SLDataType
的好处,可以很方便的更换顺序表的类型,不用一个个改。
SqList.h
文件代码如下
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include"Contact.h"
typedef CInfo SLDataType;
//typedef int SLDataType;
//把顺序表的数据结构改为通讯录的结构体类型
typedef struct SeqList
{
SLDataType* a;
int size; // 有效数据
int capacity; // 空间容量
}SL;
void SLInit(SL* ps); // 数据表初始化
void SLDestroy(SL* ps); // 数据表销毁
void SLPushFront(SL* ps, SLDataType x); // 头插
void SLPushBack(SL* ps, SLDataType x); // 尾插
void SLPopFront(SL* ps); // 头删
void SLPopBack(SL* ps); // 尾删
void SLCheckCapacity(SL* ps); // 检查内存是否足够,不够就扩容。
void SLprintf(SL* ps); // 数据表打印
void SLInsert(SL* ps, int pos, SLDataType x); //任意下标位置的插入
void SLErase(SL* ps, int pos); //任意下标位置的删除
3通讯录运行文件Contact.c
1. 通讯录的创建ContactInit
只需要调用顺序表的初始化就可以啦
void ContactInit(contact* pcon)
{
SLInit(pcon);
}
2.通讯录的销毁ContactDestroy
一样的道理,顺序表都销毁了,基于它的通讯录还好存在吗?所以自己调用顺序表的销毁就OK啦
void ContactDestroy(contact* pcon)
{
SLDestroy(pcon);
}
3.添加联系人
到这里就需要创建个通讯录结构体(info
),然后输入值到通讯录的结构体中,随便打印个提示界面,然后记得调用顺序表的尾插操作,通过info
把数据插入到顺序表中,因为顺序表的数据类型是CInfo
也就是struct ContactInfo
,所以并不冲突。
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);
SLPushBack(pcon, info);
}
4.删除联系人
有了创建自然就有删除,但是删除删除哪里了,所以还要个查找操作
int FindByName(contact* pcon,char name)
{
for (int i = 0; i < pcon->size; pcon->size++)
{
if (strcmp(pcon->size,name)==0)
{
return i;
}
}
return -1;
}
先输入用户名,然后通过用户名进行查找操作,找到了就调用顺序表的删除操作
void ContactDel(contact* pcon)
{
printf("请输入要删除的用户的名称:\n");
char name[NAME_MAX];
scanf("%s", &name);
int findidex = FindByName(pcon,name);
SLPopBack(pcon);
if (findidex < 0)
{
printf("要删除的联系人不存在");
return;
}
SLErase(pcon, findidex);
}
5.修改联系人
通过查找,
void ContactModify(contact* pcon)
{
printf("请输入要修改的用户名称:\n");
char name[NAME_MAX];
scanf("%s", name);
int find = FindByName(pcon, name);
if (find < 0)
{
printf("要修改的用户不存在!\n");
return;
}
printf("请输入新的用户名称:\n");
scanf("%s", pcon->a[find].name);
printf("请输入新的用户性别:\n");
scanf("%s", pcon->a[find].sex);
printf("请输入新的用户年龄:\n");
scanf("%s", pcon->a[find].age);
printf("请输入新的用户电话:\n");
scanf("%s", pcon->a[find].tel);
printf("请输入新的用户地址:\n");
scanf("%s", pcon->a[find].addr);
printf("修改成功\n");
}
6.打印联系人
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
);
}
}
7.查找联系人
void ContactFind(contact* pcon)
{
char name[NAME_MAX];
printf("请输入要查找的用户名称:\n");
scanf("%s", name);
int find = FindByName(pcon, name);
if (find < 0)
{
printf("该联系人不存在\n");
return;
}
printf("%s %s %d %s %s\n",
pcon->a[find].name,
pcon->a[find].sex,
pcon->a[find].age,
pcon->a[find].tel,
pcon->a[find].addr
);
}
完整代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#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);
SLPushBack(pcon, info);
}
int FindByName(contact* pcon,char name)
{
for (int i = 0; i < pcon->size; pcon->size++)
{
if (strcmp(pcon->size,name)==0)
{
return i;
}
}
return -1;
}
void ContactDel(contact* pcon)
{
printf("请输入要删除的用户的名称:\n");
char name[NAME_MAX];
scanf("%s", &name);
int findidex = FindByName(pcon,name);
SLPopBack(pcon);
if (findidex < 0)
{
printf("要删除的联系人不存在");
return;
}
SLErase(pcon, findidex);
}
void ContactModify(contact* pcon)
{
printf("请输入要修改的用户名称:\n");
char name[NAME_MAX];
scanf("%s", name);
int find = FindByName(pcon, name);
if (find < 0)
{
printf("要修改的用户不存在!\n");
return;
}
printf("请输入新的用户名称:\n");
scanf("%s", pcon->a[find].name);
printf("请输入新的用户性别:\n");
scanf("%s", pcon->a[find].sex);
printf("请输入新的用户年龄:\n");
scanf("%s", pcon->a[find].age);
printf("请输入新的用户电话:\n");
scanf("%s", pcon->a[find].tel);
printf("请输入新的用户地址:\n");
scanf("%s", pcon->a[find].addr);
printf("修改成功\n");
}
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 find = FindByName(pcon, name);
if (find < 0)
{
printf("该联系人不存在\n");
return;
}
printf("%s %s %d %s %s\n",
pcon->a[find].name,
pcon->a[find].sex,
pcon->a[find].age,
pcon->a[find].tel,
pcon->a[find].addr
);
}
4SeqList.c
顺序表的基本函数
此处存放顺序表的基本操作函数,所以无需修改,与通讯录有关的操作存放在Contact.c
文件中
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
void SLCheckCapacity(SL* ps) // 检查内存是否足够,不够就扩容。
{
if (ps->size == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity = newCapacity;
}
}
void SLprintf(SL* ps) // 数据表打印
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
void SLInit(SL* ps) // 数据表初始化
{
assert(ps);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
void SLDestroy(SL* ps) // 数据表销毁
{
assert(ps);
if (ps->a != NULL)
{
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
}
void SLPushFront(SL* ps, SLDataType x) // 头插
{
assert(ps);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;
ps->size++;
}
void SLPushBack(SL* ps, SLDataType x) // 尾插
{
assert(ps);
SLCheckCapacity(ps);
ps->a[ps->size++] = x;
}
void SLPopFront(SL* ps) // 头删
{
assert(ps);
assert(ps->size > 0);
int begin = 1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}
void SLPopBack(SL* ps) // 尾删
{
assert(ps);
assert(ps->size > 0);
ps->size--;
}
// pos是下标
void SLInsert(SL* ps, int pos, SLDataType x) // 任意下标位置的插入
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[pos] = x;
ps->size++;
}
void SLErase(SL* ps, int pos) // 任意下标位置的删除
{
assert(ps);
assert(pos >= 0 && pos < ps->size); // 这里删除不能用等于ps->size,ps->size看作下标的话相当于下标的最后一个位置+1
int begin = pos + 1;
while (begin < ps->size)
{
ps->a[begin - 1] = ps->a[begin];
begin++;
}
ps->size--;
}