C语言——史上最全通讯录讲解(附源码)
- 一、开始界面的打印
- 二、对六大板块进行定义操作
- 三、对联系人进行初始化
- 四、对通讯录进行初始化
- 4.1动态版本
- 4.2静态版本
- 五、通讯录六大功能的具体实现
- 5.1判断是否需要扩容Checkcapcity
- 5.2添加联系人ADDcontact
- 5.3删除联系人 DELcontact
- 5.3.1 Findname
- 5.3.2删除联系人
- 5.4 查找联系人 SEARCHcontact
- 5.5 修改联系人MODIFYcontac
- 5.6对联系人进行排序SORTcontact
- 5.7销毁通讯录Destory
- 5.5显示联系人信息SHOWcontact
- 六、通讯录源码
- 6.1 Contact.h
- 6.2 Contact.c
- 6.3 test.c
- 6.4 代码运行
本次通讯录的实现,我将其分为6大板块,分别是添加联系人,删除联系人,展示联系人,修改联系人,查询指定联系人,将联系人按照姓名进行排序。
一、开始界面的打印
首先我们需要创建一个美观的界面,让我们所制作的通讯录看起来更加的规范,更加的整洁,而界面的制作我们在这里就简单的运用了一下printf函数,代码如下,当然大家也可以选择自己喜欢的样式去制作一个自己喜欢的开始界面。
void menu()
{
printf("***************************\n");
printf("*****1.add 2.del*****\n");
printf("*****3.show 4.search*****\n");
printf("*****5.modify 6.sort*****\n");
printf("*****7.exit *****\n");
printf("***************************\n");
}
二、对六大板块进行定义操作
我们可以采用联合体进行对六大板块的一个定义操作,因为联合体里面的定义内容其本质上就是数字0,1,2…
enum option
{
exit,
add,
del,
show,
search,
modify,
sort
};
三、对联系人进行初始化
在contact.h中对联系人进行初始化,这里我们采用结构体的方式,对联系人的个人信息进行一定的简单初始化,为了方便日后可能需要对数字重新定义的需求,这里我们采用typedef的方式定义一些变量
#define MAX 100
#define MAX_name 20
#define MAX_sex 5
#define MAX_tele 15
#define MAX_addr 20
#define DEFAULT_sz 3
#define INC_SZ 3
通讯录的联系人的初始化
typedef struct Peopleinformatin
{
char name[MAX_name];
char sex[MAX_sex];
int age;
char tele[MAX_tele];
char addr[MAX_addr];
}Peopleinformatin;
四、对通讯录进行初始化
通讯录的初始化分为两个版本,静态版本和动态版本,其中动态版本可以通过坚持联系人的信息,来判断是否需要扩充容量。
4.1动态版本
void Initcontact(contact* pc)
{
pc->data = (Peopleinformatin*)malloc(DEFAULT_sz * sizeof(Peopleinformatin));
if (NULL == pc->data)
{
printf("初始化空间失败:%s", strerror(errno));
}
pc->sz = 0;
pc->capacity = DEFAULT_sz;
4.2静态版本
//静态版本
//初始化联系人
void Initcontact(contact* pc)
{
pc->sz = 0;
memset(pc->data, 0, sizeof(pc->data));
}
五、通讯录六大功能的具体实现
5.1判断是否需要扩容Checkcapcity
该函数可以通过判断,以达到是否需要进行扩容的目的
int Checkcapcity(contact* pc)
{
if (pc->sz == pc->capacity)//表明需要进行扩容
{
Peopleinformatin* ptr = (Peopleinformatin*)realloc(pc->data, (DEFAULT_sz + INC_SZ) * sizeof(Peopleinformatin));
if (ptr == NULL)
{
printf("扩容失败:%s", strerror(errno));
return 0;
}
else
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("扩容成功:%d", pc->capacity);
return 1;
}
return 1;
}
}
5.2添加联系人ADDcontact
通过该函数达到添加联系人各项基本信息的目的,在使用该函数前,首先要利用Checkcapcity函数来判断是否要进行扩容操作,来达到存放联系人信息的目的。
void ADDcontact(contact* pc)
{
if (Checkcapcity(pc) == 0)
{
printf("扩容失败:%s", strerror(errno));
return;
}
else
{
printf("请输入联系人姓名:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入联系人年龄:");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入联系人性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入联系人电话:");
scanf("%s", &(pc->data[pc->sz].tele));
printf("请输入联系人地址:");
scanf("%s", pc->data[pc->sz].addr);
printf("添加成功\n");
pc->sz++;
}
}
5.3删除联系人 DELcontact
对联系人进行删除操作时,我们需要先找到该联系人,所以我们先要创建一个函数来找到该联系人,在本次的通讯录中,我采用查找名字的方式,来查找联系人。
5.3.1 Findname
通过strcmp函数来比较字符串中的信息是否相同,以此来达到查找联系人的目的。
int Findname(const contact *pc,char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(pc->data[i].name, name))
{
return i;
}
}
return -1;
}
5.3.2删除联系人
通过FIndname找到联系人之后,便可以进行删除操作了。在这里我们定义了DELcontact来进行删除操作,我们在这里采用覆盖的方式,将后一个联系人的信息把前一个联系人的信息进行覆盖。
void DELcontact(contact* pc)
{
char name[MAX_name] = { 0 };
//查找联系人
printf("请输入要查找人的姓名:");
scanf("%s", name);
int pos = Findname(pc, name);
if (pos == -1)
{
printf("查询的联系人没有找到\n");
}
int i = 0;
//删除操作
for (i = 0; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
5.4 查找联系人 SEARCHcontact
void SEARCHcontact(contact* pc)
{
char name[MAX_name] = { 0 };
printf("请输入要查找人的姓名:");
scanf("%s", name);
int ret = Findname(pc, name);
if (ret == -1)
{
printf("通讯录中没有该联系人\n");
return;
}
//打印标题
printf("%-10s %-5s %-10s %-20s %-10s\n", "姓名", "性别", "年龄", "电话", "地址");
//打印数据
printf("%-10s %-5s %-10d %-20s %-10s\n", pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr);
}
5.5 修改联系人MODIFYcontac
首先对通过前文的Findname函数找到要修改的联系人信息,之后便可以对其进行修改操作。
void MODIFYcontact(contact* pc)
{
char name[MAX_name] = { 0 };
printf("请输入要修改联系人的姓名:");
scanf("%s", name);
int ret = Findname(pc, name);
if (ret == -1)
{
printf("通讯录中没有该联系人\n");
return;
}
//修改
printf("请输入姓名:");
scanf("%s", pc->data[ret].name);
printf("请输入年龄:");
scanf("%d", &(pc->data[ret].age));
printf("请输入性别:");
scanf("%s", pc->data[ret].sex);
printf("请输入电话:");
scanf("%s", pc->data[ret].tele);
printf("请输入地址:");
scanf("%s", pc->data[ret].addr);
printf("修改成功\n");
}
5.6对联系人进行排序SORTcontact
采用qsort对联系人按照姓名进行排序。
int cmp_by_name(const void* e1, const void* e2)
{
return strcmp(((Peopleinformatin*)e1)->name, ((Peopleinformatin*)e2)->name);
}
void SORTcontact(contact* pc)
{
qsort(pc->data, pc->sz, sizeof(Peopleinformatin), cmp_by_name);
printf("修改成功\n");
}
5.7销毁通讯录Destory
通过**free释放所申请的空间,并将其置为NULL**。
void Destory(contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = NULL;
pc->sz = NULL;
printf("销毁内存成功\n");
}
5.5显示联系人信息SHOWcontact
void SHOWcontact(const contact* pc)
{
//打印标题
int i = 0;
printf("%-10s %-5s %-10s %-20s %-10s\n", "姓名", "性别", "年龄", "电话", "地址");
//打印数据
for (i = 0; i < pc->sz; i++)
{
printf("%-10s %-5s %-10d %-20s %-10s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
}
}
六、通讯录源码
6.1 Contact.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#include<errno.h>
#define MAX 100
#define MAX_name 20
#define MAX_sex 5
#define MAX_tele 15
#define MAX_addr 20
#define DEFAULT_sz 3
#define INC_SZ 3
typedef struct Peopleinformatin
{
char name[MAX_name];
char sex[MAX_sex];
int age;
char tele[MAX_tele];
char addr[MAX_addr];
}Peopleinformatin;
//动态版本
typedef struct contact
{
Peopleinformatin* data;//指向存放数据的空间
int sz;//保存当前存放联系人的个数
int capacity;//通讯录的容量
}contact,*pcontact;//重新定义命名
//初始化通讯录
void Initcontact(contact *pc);
//销毁通讯录
void Destory(contact* pc);
//添加联系人
void ADDcontact(contact* pc);
//显示通讯录
void SHOWcontact(const contact* pc);
//删除联系人
void DELcontact(contact* pc);
//查询联系人
void SEARCHcontact(contact* pc);
//修改联系人信息
void MODIFYcontact(contact* pc);
//按名字对联系人信息进行排序
void SORTcontact(contact* pc);
6.2 Contact.c
#include"contact.h"
//动态版本的初始化
void Initcontact(contact* pc)
{
pc->data = (Peopleinformatin*)malloc(DEFAULT_sz * sizeof(Peopleinformatin));
if (NULL == pc->data)
{
printf("初始化空间失败:%s", strerror(errno));
}
pc->sz = 0;
pc->capacity = DEFAULT_sz;
}
//动态版本添加联系人
//判断是否需要进行扩容
int Checkcapcity(contact* pc)
{
if (pc->sz == pc->capacity)//表明需要进行扩容
{
Peopleinformatin* ptr = (Peopleinformatin*)realloc(pc->data, (DEFAULT_sz + INC_SZ) * sizeof(Peopleinformatin));
if (ptr == NULL)
{
printf("扩容失败:%s", strerror(errno));
return 0;
}
else
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("扩容成功:%d", pc->capacity);
return 1;
}
return 1;
}
}
void ADDcontact(contact* pc)
{
if (Checkcapcity(pc) == 0)
{
printf("扩容失败:%s", strerror(errno));
return;
}
else
{
printf("请输入联系人姓名:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入联系人年龄:");
scanf("%d", &(pc->data[pc->sz].age));
printf("请输入联系人性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入联系人电话:");
scanf("%s", &(pc->data[pc->sz].tele));
printf("请输入联系人地址:");
scanf("%s", pc->data[pc->sz].addr);
printf("添加成功\n");
pc->sz++;
}
}
//显示联系人
void SHOWcontact(const contact* pc)
{
//打印标题
int i = 0;
printf("%-10s %-5s %-10s %-20s %-10s\n", "姓名", "性别", "年龄", "电话", "地址");
//打印数据
for (i = 0; i < pc->sz; i++)
{
printf("%-10s %-5s %-10d %-20s %-10s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
}
}
//查找名字的函数
int Findname(const contact *pc,char name[])
{
int i = 0;
for (i = 0; i < pc->sz; i++)
{
if (0 == strcmp(pc->data[i].name, name))
{
return i;
}
}
return -1;
}
//删除联系人
void DELcontact(contact* pc)
{
char name[MAX_name] = { 0 };
//查找联系人
printf("请输入要查找人的姓名:");
scanf("%s", name);
int pos = Findname(pc, name);
if (pos == -1)
{
printf("查询的联系人没有找到\n");
}
int i = 0;
//删除操作
for (i = 0; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
//查找联系人
void SEARCHcontact(contact* pc)
{
char name[MAX_name] = { 0 };
printf("请输入要查找人的姓名:");
scanf("%s", name);
int ret = Findname(pc, name);
if (ret == -1)
{
printf("通讯录中没有该联系人\n");
return;
}
//打印标题
printf("%-10s %-5s %-10s %-20s %-10s\n", "姓名", "性别", "年龄", "电话", "地址");
//打印数据
printf("%-10s %-5s %-10d %-20s %-10s\n", pc->data[ret].name, pc->data[ret].sex, pc->data[ret].age, pc->data[ret].tele, pc->data[ret].addr);
}
//修改联系人信息
void MODIFYcontact(contact* pc)
{
char name[MAX_name] = { 0 };
printf("请输入要修改联系人的姓名:");
scanf("%s", name);
int ret = Findname(pc, name);
if (ret == -1)
{
printf("通讯录中没有该联系人\n");
return;
}
//修改
printf("请输入姓名:");
scanf("%s", pc->data[ret].name);
printf("请输入年龄:");
scanf("%d", &(pc->data[ret].age));
printf("请输入性别:");
scanf("%s", pc->data[ret].sex);
printf("请输入电话:");
scanf("%s", pc->data[ret].tele);
printf("请输入地址:");
scanf("%s", pc->data[ret].addr);
printf("修改成功\n");
}
//按名字对联系人信息进行排序
int cmp_by_name(const void* e1, const void* e2)
{
return strcmp(((Peopleinformatin*)e1)->name, ((Peopleinformatin*)e2)->name);
}
void SORTcontact(contact* pc)
{
qsort(pc->data, pc->sz, sizeof(Peopleinformatin), cmp_by_name);
printf("修改成功\n");
}
//销毁通讯录
void Destory(contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = NULL;
pc->sz = NULL;
printf("销毁内存成功\n");
}
6.3 test.c
#include"contact.h"
void menu()
{
printf("**********************************\n");
printf("**** 1.ADD 2.DEL ****\n");
printf("**** 3.SHOW 4.SEARCH****\n");
printf("**** 5.MODIFY 6.SORT ****\n");
printf("**** 0.EXIT ****\n");
printf("**********************************\n");
}
enum option
{
EXIT,
ADD,
DEL,
SHOW,
SEARCH,
MODIFY,
SORT
};
int main()
{
int input = 0;
contact con;
Initcontact(&con);//初始化通讯录
menu();
do
{
printf("请选择您要执行的功能:\n");
scanf("%d", &input);
switch (input)
{
case EXIT:
Destory(&con);
printf("您已成功退出通讯录\n");
break;
case ADD:
ADDcontact(&con);
break;
case DEL:
DELcontact(&con);
break;
case SHOW:
SHOWcontact(&con);
break;
case SEARCH:
SEARCHcontact(&con);
break;
case MODIFY:
MODIFYcontact(&con);
break;
case SORT:
SORTcontact(&con);
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}