通讯录的实现(三种方式)

通讯录的实现

  • 一.通讯录的实现(静态版本)
    • 1.通讯录实现前的准备工作
      • (1)菜单的实现
      • (2)结构体的实现
      • (3)菜单选项功能实现
      • (4)全局变量的定义
    • 2.通讯录功能实现
      • (1)初始化通讯录
      • (1)添加联系人信息
      • (2)打印联系人信息
      • (3)删除联系人信息
      • (4)查找联系人信息
      • (5)修改联系人信息
      • (6)排序所有联系人
  • 二.通讯录的实现(动态版本)
    • 1.结构体的更改
    • 2.初始化通讯录函数更改
    • 3.添加联系人函数更改
    • 4.释放内存
  • 三.通讯录的实现(文件版本)
    • 1.通讯录信息写入文件
    • 2.文件信息输出至通讯录

一.通讯录的实现(静态版本)

通讯录的功能:
通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址。

  • 添加联系人信息
  • 删除指定联系人信息
  • 查找指定联系人信息
  • 修改指定联系人信息
  • 显示所有联系人信息
  • 排序所有联系人

1.通讯录实现前的准备工作

(1)菜单的实现

test .c

void menu()
{
	printf("**************************************\n");
	printf("******   1.add       2.sub   *********\n");
	printf("******   3.search    4.modify   ******\n");
	printf("******   5.sort      6.print    ******\n");
	printf("************    0.exit     ***********\n");
	printf("**************************************\n");
}

(2)结构体的实现

在这儿我们需要创建两个结构体,一个用来存放人的信息:姓名、性别、年龄、电话、住址;另一个用来存放通讯录的信息。
contact.h

typedef struct PeoInfo
{
	char name[NAME_MAX];//姓名
	int age;//年龄
	char sex[SEX_MAX];//性别
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//地址
}PeoInfo;

typedef struct Contact
{
	PeoInfo data[MAX];//存储联系人的信息
	int count;//存储联系人的数量
}Contact;

(3)菜单选项功能实现

我们需要根据用户的需求进行选择,比如用户输入1,我们就知道他是要添加联系人,输入0,就是退出通讯录,在这儿我们可以用到枚举,将选择一一列举出来:
contact.h

enum Point
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};

test .c

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			break;
		case DEL:
			break;
		case SEARCH:
			break;
		case MODIFY:
			break;
		case SORT:
			break;
		case PRINT:
			break;
		case EXIT:
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

(4)全局变量的定义

为了能更好的对我们的通讯录进行,我们将一些代码中需要多次出现的数使用#define进行定义:

#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 20

2.通讯录功能实现

(1)初始化通讯录

首先我们得先创建一个通讯录,然后对通讯录进行初始化:
test .c

Contact con;//创建一个通讯录
Init_Contact(&con);//初始化通讯录

contact .c

void Init_Contact(Contact* pc)
{
	pc->count = 0;//通讯录初始数量为0
	memset(pc->data, 0, sizeof(pc->data));//将存储联系人数组中每个人的信息初始化为0
}

contact .h

void Init_Contact(Contact* pc);

(1)添加联系人信息

我们添加联系人信息的时候首先要得判断通讯是否满了,如果通讯满了,我们就添加不了,如果没满,我们就开始添加。
contact .c

void Add_Contact(Contact* pc)
{
	assert(pc);
	if (pc->count == MAX)
	{
		printf("通讯录已满,无法添加\n");
	}
	else 
	{
		printf("开始添加\n");
		printf("请输入添加人的姓名:");
		scanf("%s", pc->data[pc->count].name);
		printf("请输入添加人的年龄:");
		scanf("%d", &(pc->data[pc->count].age));
		printf("请输入添加人的性别:");
		scanf("%s", pc->data[pc->count].sex);
		printf("请输入添加人的电话:");
		scanf("%s", pc->data[pc->count].tele);
		printf("请输入添加人的地址:");
		scanf("%s", pc->data[pc->count].addr);
		pc->count++;
		printf("添加成功\n");
	}
}

contact .h

void Add_Contact(Contact* pc)

(2)打印联系人信息

我们添加完联系人的信息以后,得看看我们添加的信息对不对,所以得把联系人打印出来看一看:
contact .c

void Print_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%20s %5s %5s %12s %12s\n","姓名", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%20s %5d %5s %12s %12s\n",pc->data[i].name, pc->data[i].age, pc->data[i].sex, 
			pc->data[i].tele, pc->data[i].addr);
	}
}

contact .h

void Print_Contact(Contact* pc);

(3)删除联系人信息

删除联系人的前提是我们的先找到这个联系人,然后再删除,而删除联系人实际上就是把要删除的这个联系人的信息全给覆盖掉。也就是让他后面的每个联系人往前移动一位就行了。我们这儿就以查找姓名为例吧:
contact .c

static int find_by_name(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(name, pc->data[i].name) == 0)
		{
			return i;
		}
	}
	return 0;
}
void Del_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	//查找联系人
	char name[MAX];
	printf("请输入要删除的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc,name);
	if (pos)
	{
		for (i = pos; i < pc->count - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->count--;
		printf("删除成功\n");
	}
	else
	{
		printf("要删除的人不存在\n");
	}
}

contact .h

void Del_Contact(Contact* pc);

在这儿要注意的是,我们删除一个联系人的信息以后,count是要进行减减的。

(4)查找联系人信息

查找联系人就是输入联系人的某个信息,然后找到了在打印出来,我们依然以查找姓名为例:
contact .c

void Search_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	char name[MAX];
	printf("请输入要查找的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc, name);
	if (pos)
	{
		printf("%20s %5s %5s %12s %12s\n", "姓名", "年龄", "性别", "电话", "地址");
		printf("%20s %5d %5s %12s %12s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex,
			pc->data[pos].tele, pc->data[pos].addr);
	}
	else 
	{
		printf("要查找的人不存在\n");
	}
}

contact .h

void Search_Contact(Contact* pc);

(5)修改联系人信息

修改联系人其实也一样,就是输先把这个联系人找到,找到了之后逐项进行修改,我们依然以查找姓名为例:
contact .c

void Modify_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	char name[MAX];
	printf("请输入要修改的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc, name);
	if (pos)
	{
		printf("开始修改\n");
		printf("请输入修改人的姓名:");
		scanf("%s", pc->data[pos].name);
		printf("请输入修改人的年龄:");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入修改人的性别:");
		scanf("%s", pc->data[pos].sex);
		printf("请输入修改人的电话:");
		scanf("%s", pc->data[pos].tele);
		printf("请输入修改人的地址:");
		scanf("%s", pc->data[pos].addr);
		printf("修改成功\n");
	}
	else
	{
		printf("要修改的人不存在\n");
	}
}

contact .h

void Modify_Contact(Contact* pc);

(6)排序所有联系人

在这儿我们可以使用我们的qsort函数,当然,我们也可以自己将冒泡排序函数改造一番:
contact .c

//排序所以联系人
static int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}

static void swap(char* buf1, char* buf2, size_t width)
{
	unsigned int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

static void my_bubble_sort(void* base, size_t num, size_t width, int(*cmp)(const void* e1, const void* e2))
{
	unsigned int i = 0;
	unsigned int j = 0;
	for (i = 0; i < num-1; i++)
	{
		for (j = 0; j < num - 1 - i; j++)
		{
			if (cmp_by_name((char*)base + j * width, (char*)base + (j + 1) * width )> 0)
			{
				swap(((char*)base + j * width), ((char*)base + (j + 1) * width), width);
			}
		}
	}

}
void Sort_Contact(Contact* pc)
{
	my_bubble_sort(pc->data, pc->count, sizeof(PeoInfo), cmp_by_name);
	printf("排序成功\n");
}

contact .h

void Sort_Contact(Contact* pc);

整体代码:
test.c

#include"contact.h"


void menu()
{
	printf("**************************************\n");
	printf("******   1.add       2.del   *********\n");
	printf("******   3.search    4.modify   ******\n");
	printf("******   5.sort      6.print    ******\n");
	printf("************    0.exit     ***********\n");
	printf("**************************************\n");
}
int main()
{
	Contact con;//创建一个通讯录
	Init_Contact(&con);//初始化通讯录

	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			//添加联系人
			Add_Contact(&con);
			break;
		case DEL:
			//删除联系人
			Del_Contact(&con);
			break;
		case SEARCH:
			//查找联系人
			Search_Contact(&con);
			break;
		case MODIFY:
			//修改联系人
			Modify_Contact(&con);
			break;
		case SORT:
			//排序所有联系人
			Sort_Contact(&con);
			break;
		case PRINT:
			//打印联系人
			Print_Contact(&con);
			break;
		case EXIT:
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

contact .c

#include"contact.h"

//初始化通讯录
void Init_Contact(Contact* pc)
{
	assert(pc);
	pc->count = 0;
	memset(pc->data, 0, sizeof(pc->data));
}
//添加联系人
void Add_Contact(Contact* pc)
{
	assert(pc);
	if (pc->count == MAX)
	{
		printf("通讯录已满,无法添加\n");
	}
	else 
	{
		printf("开始添加\n");
		printf("请输入添加人的姓名:");
		scanf("%s", pc->data[pc->count].name);
		printf("请输入添加人的年龄:");
		scanf("%d", &(pc->data[pc->count].age));
		printf("请输入添加人的性别:");
		scanf("%s", pc->data[pc->count].sex);
		printf("请输入添加人的电话:");
		scanf("%s", pc->data[pc->count].tele);
		printf("请输入添加人的地址:");
		scanf("%s", pc->data[pc->count].addr);
		pc->count++;
		printf("添加成功\n");
	}
}

//打印联系人
void Print_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%20s %5s %5s %12s %12s\n","姓名", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%20s %5d %5s %12s %12s\n",pc->data[i].name, pc->data[i].age, pc->data[i].sex, 
			pc->data[i].tele, pc->data[i].addr);
	}
}

//删除联系人
static int find_by_name(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(name, pc->data[i].name) == 0)
		{
			return i;
		}
	}
	return 0;
}
void Del_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	//查找联系人
	char name[MAX];
	printf("请输入要删除的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc,name);
	if (pos)
	{
		for (i = pos; i < pc->count - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->count--;
		printf("删除成功\n");
	}
	else
	{
		printf("要删除的人不存在\n");
	}
}

//查找联系人
void Search_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	//查找联系人
	char name[MAX];
	printf("请输入要查找的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc, name);
	if (pos)
	{
		printf("%20s %5s %5s %12s %12s\n", "姓名", "年龄", "性别", "电话", "地址");
		printf("%20s %5d %5s %12s %12s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex,
			pc->data[pos].tele, pc->data[pos].addr);
	}
	else 
	{
		printf("要查找的人不存在\n");
	}
}

//修改联系人
void Modify_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	//查找联系人
	char name[MAX];
	printf("请输入要修改的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc, name);
	if (pos)
	{
		printf("开始修改\n");
		printf("请输入修改人的姓名:");
		scanf("%s", pc->data[pos].name);
		printf("请输入修改人的年龄:");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入修改人的性别:");
		scanf("%s", pc->data[pos].sex);
		printf("请输入修改人的电话:");
		scanf("%s", pc->data[pos].tele);
		printf("请输入修改人的地址:");
		scanf("%s", pc->data[pos].addr);
		printf("修改成功\n");
	}
	else
	{
		printf("要修改的人不存在\n");
	}
}

//排序所以联系人
static int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}

static void swap(char* buf1, char* buf2, size_t width)
{
	unsigned int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

static void my_bubble_sort(void* base, size_t num, size_t width, int(*cmp)(const void* e1, const void* e2))
{
	unsigned int i = 0;
	unsigned int j = 0;
	for (i = 0; i < num-1; i++)
	{
		for (j = 0; j < num - 1 - i; j++)
		{
			if (cmp_by_name((char*)base + j * width, (char*)base + (j + 1) * width )> 0)
			{
				swap(((char*)base + j * width), ((char*)base + (j + 1) * width), width);
			}
		}
	}

}
void Sort_Contact(Contact* pc)
{
	my_bubble_sort(pc->data, pc->count, sizeof(PeoInfo), cmp_by_name);
	printf("排序成功\n");
}

contact .h

#include
#include
#include

#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 20

enum Point
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};
typedef struct PeoInfo
{
	char name[NAME_MAX];//姓名
	int age;//年龄
	char sex[SEX_MAX];//性别
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//地址
}PeoInfo;

typedef struct Contact
{
	PeoInfo data[MAX];//存储联系人的信息
	int count;//存储联系人的数量
}Contact;
//初始化通讯录
void Init_Contact(Contact* pc);
//添加联系人
void Add_Contact(Contact* pc);
//打印联系人
void Print_Contact(Contact* pc);
//删除联系人
void Del_Contact(Contact* pc);
//查找联系人
void Search_Contact(Contact* pc);
//修改联系人
void Modify_Contact(Contact* pc);
//排序所以联系人
void Sort_Contact(Contact* pc);

到这儿我们静态版本的通讯录就实现了。接下来就是动态版本的:

二.通讯录的实现(动态版本)

在静态版本通讯录中,我们通讯录的空间开辟了以后就不能更改,如果觉得他大了或者是小了,需要去更改全局变量的才可以,而在程序运行过程中无法更改,接下来我们就实现一个动态版本的,可以自己进行扩容,减少空间的浪费:

1.结构体的更改

//静态版本
//typedef struct Contact
//{
//	PeoInfo data[MAX];//存储联系人的信息
//	int count;//存储联系人的数量
//}Contact;

//动态版本
typedef struct Contact
{
	PeoInfo* data;//存储联系人的信息
	int count;//存储联系人的数量
	int capacity;//通讯录的初始容量
}Contact;

在这儿,我们将数组改成了结构体指针的形式,并且增加一个capacity变量表示通讯录的容量,有了这两个条件,我们就了使用动态内存开辟函数进行空间的开辟。

2.初始化通讯录函数更改

我们假设通讯录初始容量为“3”吧,然后将空间开辟出来:

#define INT_SZ 3
//静态版本
//初始化通讯录
//void Init_Contact(Contact* pc)
//{
//	assert(pc);
//	pc->count = 0;
//	memset(pc->data, 0, sizeof(pc->data));
//}

//动态版本
void Init_Contact(Contact* pc)
{
	assert(pc);
	pc->count = 0;
	pc->capacity = INT_SZ;
	pc->data = (PeoInfo*)calloc(INT_SZ, sizeof(PeoInfo));
	//calloc函数开辟完空间后会自动初始化为0;
	if (pc->data == NULL)
	{
		perror("Init_Contact::calloc");
		return;
	}
}

3.添加联系人函数更改

通讯录的初始容量是“3”,如果大于3我们就需要进行扩容,我们假设每次扩容2个大小空间,此时就用到了realloc函数:

#define DEFAULT_SZ 2
static void check(Contact* pc)
{
	if (pc->count == pc->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_SZ) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
		}
		else
		{
			perror("Add_Contact::check::realloc");
			return;
		}
		pc->capacity += DEFAULT_SZ;
		printf("增容成功\n");
	}
}
void Add_Contact(Contact* pc)
{
	assert(pc);
	check(pc);
	printf("开始添加\n");
	printf("请输入添加人的姓名:");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入添加人的年龄:");
	scanf("%d", &(pc->data[pc->count].age));
	printf("请输入添加人的性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入添加人的电话:");
	scanf("%s", pc->data[pc->count].tele);
	printf("请输入添加人的地址:");
	scanf("%s", pc->data[pc->count].addr);
	pc->count++;
	printf("添加成功\n");
}

4.释放内存

我们在使用动态内存开辟空间以后,最后是需要进行释放的,不然会造成动态内存的泄露,所以,我们在退出通讯录的时候对空间进行释放:
contact.h

void Destory_Contact(Contact* pc);

contact.c

void Destory_Contact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->count = 0;
	pc->capacity = 0;
}

三.通讯录的实现(文件版本)

1.通讯录信息写入文件

动态版本通讯录实现以后,我们会发现,只要退出程序,通讯录的信息就自己销毁了,没有保存下来,接下来我们把他优化成文件版本的,在退出程序之前将通讯录的信息保存下来:
contact.h

void Save_Contact(Contact* pc);

contact.c

void Save_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	FILE* pfwrite = fopen("contact.txt", "wb");
	if (NULL == pfwrite)
	{
		perror("Save_Contact::");
		return ;
	}
	for (i = 0; i < pc->count; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pfwrite);
	}
	fclose(pfwrite);
	pfwrite = NULL;
}

2.文件信息输出至通讯录

什么时候将文件信息输出至通讯录呢?当然是初始化的时候,在初始化的时候将文件中的信息导入到通讯录中,因为初始化通讯录容量为3,所以我们在这儿还需要考虑增容的问题,我们将check函数放在文件的开头:

void check(Contact* pc)
{
	if (pc->count == pc->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_SZ) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
		}
		else
		{
			perror("Add_Contact::check::realloc");
			return;
		}
		pc->capacity += DEFAULT_SZ;
		printf("增容成功\n");
	}
}
 void Load_Contact(Contact* pc) 
{
	FILE* pfread = fopen("contact.txt", "rb");
	if (pfread == NULL)
	{
		perror("Load_Contact::");
		return;
	}
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo),1, pfread) == 1)
	{
		check(pc);
		pc->data[pc->count] = tmp;
		pc->count++;
	}
	fclose(pfread);
	pfread = NULL;
}
void Init_Contact(Contact* pc)
{
	assert(pc);
	pc->count = 0;
	pc->capacity = INT_SZ;
	pc->data = (PeoInfo*)calloc(INT_SZ, sizeof(PeoInfo));
	//calloc函数开辟完空间后会自动初始化为0;
	if (pc->data == NULL)
	{
		perror("Init_Contact::calloc");
		return;
	}
	Load_Contact(pc);
}

整体代码:
contact.h

#include
#include
#include
#include

#define MAX 1000
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 20
#define INT_SZ 3
#define DEFAULT_SZ 2

enum Point
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SORT,
	PRINT
};
typedef struct PeoInfo
{
	char name[NAME_MAX];//姓名
	int age;//年龄
	char sex[SEX_MAX];//性别
	char tele[TELE_MAX];//电话
	char addr[ADDR_MAX];//地址
}PeoInfo;
//静态版本
//typedef struct Contact
//{
//	PeoInfo data[MAX];//存储联系人的信息
//	int count;//存储联系人的数量
//}Contact;
//动态版本
typedef struct Contact
{
	PeoInfo* data;//存储联系人的信息
	int count;//存储联系人的数量
	int capacity;//通讯录的初始容量
}Contact;

//初始化通讯录
void Init_Contact(Contact* pc);
//添加联系人
void Add_Contact(Contact* pc);
//打印联系人
void Print_Contact(Contact* pc);
//删除联系人
void Del_Contact(Contact* pc);
//查找联系人
void Search_Contact(Contact* pc);
//修改联系人
void Modify_Contact(Contact* pc);
//排序所有联系人
void Sort_Contact(Contact* pc);
//释放内存
void Destory_Contact(Contact* pc);
//保存通讯录
void Save_Contact(Contact* pc);

contact.c

#include"contact.h"

//初始化通讯录
//void Init_Contact(Contact* pc)
//{
//	assert(pc);
//	pc->count = 0;
//	memset(pc->data, 0, sizeof(pc->data));
//}
 //初始化通讯录
void check(Contact* pc)
{
	if (pc->count == pc->capacity)
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + DEFAULT_SZ) * sizeof(PeoInfo));
		if (ptr != NULL)
		{
			pc->data = ptr;
		}
		else
		{
			perror("Add_Contact::check::realloc");
			return;
		}
		pc->capacity += DEFAULT_SZ;
		printf("增容成功\n");
	}
}
 void Load_Contact(Contact* pc) 
{
	FILE* pfread = fopen("contact.txt", "rb");
	if (pfread == NULL)
	{
		perror("Load_Contact::");
		return;
	}
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo),1, pfread) == 1)
	{
		check(pc);
		pc->data[pc->count] = tmp;
		pc->count++;
	}
	fclose(pfread);
	pfread = NULL;
}
void Init_Contact(Contact* pc)
{
	assert(pc);
	pc->count = 0;
	pc->capacity = INT_SZ;
	pc->data = (PeoInfo*)calloc(INT_SZ, sizeof(PeoInfo));
	//calloc函数开辟完空间后会自动初始化为0;
	if (pc->data == NULL)
	{
		perror("Init_Contact::calloc");
		return;
	}
	Load_Contact(pc);
}
//添加联系人
void Add_Contact(Contact* pc)
{
	assert(pc);
	check(pc);
	printf("开始添加\n");
	printf("请输入添加人的姓名:");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入添加人的年龄:");
	scanf("%d", &(pc->data[pc->count].age));
	printf("请输入添加人的性别:");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入添加人的电话:");
	scanf("%s", pc->data[pc->count].tele);
	printf("请输入添加人的地址:");
	scanf("%s", pc->data[pc->count].addr);
	pc->count++;
	printf("添加成功\n");
}

//打印联系人
void Print_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%20s %5s %5s %12s %12s\n","姓名", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%20s %5d %5s %12s %12s\n",pc->data[i].name, pc->data[i].age, pc->data[i].sex, 
			pc->data[i].tele, pc->data[i].addr);
	}
}

//删除联系人
static int find_by_name(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(name, pc->data[i].name) == 0)
		{
			return i;
		}
	}
	return 0;
}
void Del_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	//查找联系人
	char name[MAX];
	printf("请输入要删除的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc,name);
	if (pos)
	{
		for (i = pos; i < pc->count - 1; i++)
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->count--;
		printf("删除成功\n");
	}
	else
	{
		printf("要删除的人不存在\n");
	}
}
//查找联系人
void Search_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	//查找联系人
	char name[MAX];
	printf("请输入要查找的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc, name);
	if (pos)
	{
		printf("%20s %5s %5s %12s %12s\n", "姓名", "年龄", "性别", "电话", "地址");
		printf("%20s %5d %5s %12s %12s\n", pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex,
			pc->data[pos].tele, pc->data[pos].addr);
	}
	else 
	{
		printf("要查找的人不存在\n");
	}
}
//修改联系人
void Modify_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	//查找联系人
	char name[MAX];
	printf("请输入要修改的联系人的名字:");
	scanf("%s", name);
	int pos = find_by_name(pc, name);
	if (pos)
	{
		printf("开始修改\n");
		printf("请输入修改人的姓名:");
		scanf("%s", pc->data[pos].name);
		printf("请输入修改人的年龄:");
		scanf("%d", &(pc->data[pos].age));
		printf("请输入修改人的性别:");
		scanf("%s", pc->data[pos].sex);
		printf("请输入修改人的电话:");
		scanf("%s", pc->data[pos].tele);
		printf("请输入修改人的地址:");
		scanf("%s", pc->data[pos].addr);
		printf("修改成功\n");
	}
	else
	{
		printf("要修改的人不存在\n");
	}
}
//排序所以联系人
static int cmp_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
static void swap(char* buf1, char* buf2, size_t width)
{
	unsigned int i = 0;
	for (i = 0; i < width; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}
static void my_bubble_sort(void* base, size_t num, size_t width, int(*cmp)(const void* e1, const void* e2))
{
	unsigned int i = 0;
	unsigned int j = 0;
	for (i = 0; i < num-1; i++)
	{
		for (j = 0; j < num - 1 - i; j++)
		{
			if (cmp_by_name((char*)base + j * width, (char*)base + (j + 1) * width )> 0)
			{
				swap(((char*)base + j * width), ((char*)base + (j + 1) * width), width);
			}
		}
	}
}
void Sort_Contact(Contact* pc)
{
	my_bubble_sort(pc->data, pc->count, sizeof(PeoInfo), cmp_by_name);
	printf("排序成功\n");
}
//释放内存
void Destory_Contact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->count = 0;
	pc->capacity = 0;
}
//保存通讯录
void Save_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	FILE* pfwrite = fopen("contact.txt", "wb");
	if (NULL == pfwrite)
	{
		perror("Save_Contact::");
		return ;
	}
	for (i = 0; i < pc->count; i++)
	{
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pfwrite);
	}
	fclose(pfwrite);
	pfwrite = NULL;
}

test.c

#include"contact.h"


void menu()
{
	printf("**************************************\n");
	printf("******   1.add       2.del   *********\n");
	printf("******   3.search    4.modify   ******\n");
	printf("******   5.sort      6.print    ******\n");
	printf("************    0.exit     ***********\n");
	printf("**************************************\n");
}
int main()
{
	Contact con;//创建一个通讯录
	Init_Contact(&con);//初始化通讯录

	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			//添加联系人
			Add_Contact(&con);
			break;
		case DEL:
			//删除联系人
			Del_Contact(&con);
			break;
		case SEARCH:
			//查找联系人
			Search_Contact(&con);
			break;
		case MODIFY:
			//修改联系人
			Modify_Contact(&con);
			break;
		case SORT:
			//排序所有联系人
			Sort_Contact(&con);
			break;
		case PRINT:
			//打印联系人
			Print_Contact(&con);
			break;
		case EXIT:
			//保存通讯录
			Save_Contact(&con);
			Destory_Contact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
	return 0;
}

你可能感兴趣的:(c语言)