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看作下标的话相当于下标的最后一个位置+1int begin = pos + 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];begin++;}ps->size--;
}