当前使用VS2019编译器
首先建立2个源文件test.c和contect.c以及1个头文件contect.h
void menu()
{
printf("******** 1.Add 2.Del ***********************\n");
printf("******** 3.Search 4.Modify ***********************\n");
printf("******** 5.Sort 6.Print ***********************\n");
printf("******** 7.Destroy 0.Exit ***********************\n");
printf("****************************************************\n");
}
typedef struct PeoInfo//该结构体变量用来存储个人的信息
{
char name[NAME_MAX];//以下数组中的值为#define的宏定义
char sex[SEX_MAX];
int age;
char tele[TELE_MAX];
char addr[ADDR_MAX];
}PeoInfo;
typedef struct Contect//静态版本
{
PeoInfo data[MAX];//用来储存MAX个PeoInfo类型的数据
int sz;//用来记录当前通讯录人数的个数
}Contect;//重命名
typedef struct Contect//动态版本
{
PeoInfo* data;
int sz;
int capacity;
}Contect;
enum Select {//该枚举常量为通讯录菜单中的选择
EXIT,
ADD,
DEL,
SEARCH,
MODIFY,
SORT,
PRINT,
DESTROY
};
enum Modify {//该枚举常量为通讯录中修改函数中菜单的选择
NAME=1,
SEX,
AGE,
TELE,
ADDR
};
void test()
{
int input = 0;
Contect con;//定义一个Contect类型的变量
InitContect(&con);//初始化
do {
menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)//下面的case语句中的常量为枚举常量
{
case ADD:
AddContect(&con);
break;
case DEL:
DelContect(&con);
break;
case SEARCH:
SearchContect(&con);
break;
case MODIFY:
ModifyContect(&con);
break;
case SORT:
SortContect(&con);
break;
case PRINT:
PrintContect(&con);
break;
case DESTROY:
DestroyContect(&con);
break;
case EXIT:
printf("退出程序");
break;
default:
printf("选择错误");
break;
}
} while (input);
}
//初始化
void InitContect(Contect* pc);
//增加内容
void AddContect(Contect* pc);
//打印
void PrintContect(Contect* pc);
//删除内容
void DelContect(Contect* pc);
//查找内容
void SearchContect(const Contect* pc);
//修改内容
void ModifyContect(Contect* pc);
//排序内容
void SortContect(Contect* pc);
//销毁
void DestroyContect(Contect* pc);
//静态版本
void InitContect(Contect* pc)
{
assert(pc);//判断是否为NULL
memset(pc->data, 0, sizeof(pc->data));
pc->sz = 0;
}
memset的作用是将缓冲区设置为指定的字符'0'
//动态版本
void InitContect(Contect* pc)
{
assert(pc);
pc->sz = 0;
pc->capacity = DEFAULT_SZ;//设置初始化能存DEFAULT_SZ个数据,其中DEFAULT_SZ为宏定义的内容
pc->data = (PeoInfo*)malloc(pc->capacity * sizeof(PeoInfo));//用malloc动态分配内存给data数组
if (pc->data==NULL)
{
perror("InitContect::malloc");//显示动态分配内存出错的信息
return;
}
memset(pc->data, 0, pc->capacity * sizeof(PeoInfo));
}
malloc用来分配内存,单位为字节
void AddContect(Contect* pc)
{
assert(pc);
//静态版本
if (pc->sz == MAX)
{
printf("通讯录已满,无法添加");
return;
}
printf("请输入名字:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
void AddContect(Contect* pc)
{
assert(pc);
//动态版本
CheckCapacity(pc);//该函数用来判断当前通讯录能够存储的内容是否达到最大值
printf("请输入名字:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加成功\n");
}
void CheckCapacity(Contect* pc)
{
assert(pc);
if (pc->sz == pc->capacity)//sz为当前通讯录中数据的个数,capacity为当前通讯录中最多能存储数据的个数
{
PeoInfo* tmp = (PeoInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PeoInfo));//每次增加2个存储数据的空间
if (tmp != NULL)
{
pc->data = tmp;//tmp不等于空指针说明内存分配成功,将成功分配的内存给data数组
}
else
{
perror("CheckCapacity::realloc");//内存分配失败的原因
return;
}
pc->capacity += 2;
printf("增容成功\n");
}
}
realloc 的作用为重新分配内存块,能增能减
void DelContect(Contect* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("请输入要删除的姓名:");
scanf("%s", name);
int ret = Search_by_name(pc, name);//找到想要删除的对象
if (-1 == ret)
{
printf("无法找到该内容\n");
return;
}
for (int i = ret; i < pc->sz - 1; i++)//将删除对象后面的数据往前移
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
void SearchContect(const Contect* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("请输入要查找的姓名:");
scanf("%s", name);
int pos = Search_by_name(pc, name);//通过名字查找
if (-1 == pos)
{
printf("无法找到该内容\n");
}
else
{
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr);
}
}
int Search_by_name(Contect* pc, char name[])
{
assert(pc);
for (int i = 0; i < pc->sz; i++)
{
if (0 == strcmp(name, pc->data[i].name))//strcmp为字符串的比较,不懂的详见上一篇
{
return i;
}
}
return -1;
}
修改菜单:
void MENU()
{
printf("********** 1.name 2.sex **********\n");
printf("********** 3.age 4.tele **********\n");
printf("********** 5.addr 0.exit **********\n");
}
void ModifyContect(Contect* pc)
{
assert(pc);
char name[NAME_MAX] = { 0 };
printf("请输入要修改的人的姓名:");
scanf("%s", name);
int ret = Search_by_name(pc, name);//找到要修改的对象
if (-1 == ret)
{
printf("无法找到要修改的人的信息\n");
return;
}
int input = 0;
do {
MENU();
printf("请选择要修改的内容:");
scanf("%d", &input);
switch (input)
{
case NAME:
printf("请输入名字:");
scanf("%s", pc->data[ret].name);
printf("修改成功\n");
break;
case SEX:
printf("请输入性别:");
scanf("%s", pc->data[ret].sex);
printf("修改成功\n");
break;
case AGE:
printf("请输入年龄:");
scanf("%d", &(pc->data[ret].age));
printf("修改成功\n");
break;
case TELE:
printf("请输入电话:");
scanf("%s", pc->data[ret].tele);
printf("修改成功\n");
break;
case ADDR:
printf("请输入地址:");
scanf("%s", pc->data[ret].addr);
printf("修改成功\n");
break;
case EXIT:
printf("退出修改程序\n");
break;
default:
printf("输入错误\n");
break;
}
} while (input);
}
void SortContect(Contect* pc)
{
assert(pc);
qsort(pc->data, pc->sz, sizeof(PeoInfo), compare);//使用qsort库函数进行排序
printf("排序成功\n");
}
该函数最后一个参数内容为自定义函数,以要通过什么内容来进行排序编写函数
int compare(const void* e1, const void* e2)
{
return strcmp(((struct PeoInfo*)e1)->name, ((struct PeoInfo*)e2)->name);
}
void PrintContect(Contect* pc)
{
assert(pc);
if (0 == pc->sz)
{
printf("通讯录中无内容\n");
}
else
printf("%-20s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "地址");
for (int i = 0; i < pc->sz; i++)
{
printf("%-20s %-5d %-5s %-12s %-30s\n", pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr);
}
}
void DestroyContect(Contect* pc)
{
free(pc->data);/需要通过free函数来进行释放动态分配的内存空间否则会导致内存泄露
pc->sz = 0;
pc->capacity = 0;
pc->data = NULL;
printf("销毁成功\n");
}