C语言_文件版动态内存管理通讯录

目录

1. 文件操作下的通讯录有何优越性

2. 通讯录模版

2.1 主函数(main)

2.2 通讯录菜单

2.3 通讯录枚举类型的声明

2.4 初始化通讯录

2.5 增加好友的功能函数

2.6 显示好友的功能函数

2.7 删除好友的功能函数

2.8 查找好友的功能函数

2.9 修改好友的功能函数

2.10 排序好友的功能函数

2.11 清除好友的功能函数

2.12 摧毁通讯录的功能函数

2.13 保存通讯录的功能函数

3. 总的程序代码

3.1 main.c

3.2 contact.c

3.3 contact.h


1. 文件操作下的通讯录有何优越性

通过对文件操作的学习,我们知道文件操作可以把相关程序写入文件中;如果把这付诸到通讯录中,就可以实现当我们关闭通讯录后,所完成的操作将保存下来,对我们来说是非常有利的;接下来我们将文件操作付诸到通讯录中;

2. 通讯录模版

2.1 主函数(main)

int main()
{
	int input = 0;//通讯录中当前有几个元素,也可以说是通讯录所要实现的功能有多少,增加、删除
	//修改等,每个功能对应一个数字,通讯录首先最需要考虑的就是用户的需求,加好友或者 ……
	struct Contact con;//创建通讯录,通过结构体的成员变量来表达,增加了代码的可读性
	InitContact(&con);//初始化通讯录
	do//do while 循环保证不管程序正确与否的前提下,我先运行一次菜单,输入用户的需求
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);//用户输入需要,加好友、删好友、修改好友情况等等
		switch (input)//switch case 进行判断,我要进行哪种功能,对应哪种需要,进入哪种情况
		{
			//添加好友
		case ADD:
			AddContact(&con);
			break;
			//删除好友
		case DEL:
			DelContact(&con);
			break;
			//查找好友
		case SEARCH:
			SearchContact(&con);
			break;
			//修改好友信息
		case MODIFY:
			ModifyContact(&con);
			break;
			//显示已经处理过的好友信息,也可以说是打印出信息
		case SHOW:
			ShowContact(&con);
			break;
			//将好友进行分类
		case SORT:
			SortContact(&con);
			break;
			//清空通讯录
		case CLEAR:
			ClearContact(&con);
			break;
			//退出
		case EXIT:
			SaveContact(&con);
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
			//switch选择的情况,也可以说是功能不在菜单里
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);//只要通讯录的功能在case 里有显示,就进行do while 循环;
	return 0;
}//因为所有case的功能函数都是传址调用,所以对应的外部函数都需要用指针来接收传过去的地址

2.2 通讯录菜单

void menu()
{
	printf("************************************\n");
	printf("****** 1. add       2. del    ******\n");
	printf("****** 3. search    4. modify ******\n");
	printf("****** 5. show      6. sort   ******\n");
	printf("****** 7. clear     0. exit   ******\n");
	printf("************************************\n");
}
// 主函数调用menu函数,menu()放在主函数do while循环体中首行,保证程序一旦运行,首先出现的就是供用
//    户选择的菜单,菜单上对应增加、删除、查找、修改、显示、分类、离开通讯录等功能,每个功能对应每
//  个不同的代码1 2 3 4 5 6 0,  为了防止修改数字而影响主函数case的使用,可以进行宏定义或者枚举,                //    本程序  我们采用的是枚举

2.3 通讯录枚举类型的声明

enum Option
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,//3
	MODIFY,//4
	SHOW,//5
	SORT//6
    CLEAR//7
};
//通过枚举来进行通讯录功能的声明,可以大大增加代码的可读性

2.4 初始化通讯录

void LoadContact(struct Contact* ps)//我将上一次操作的通讯录人员在下次打开通讯录时呈现面临两个问题:
//1.如果我上次加了5个好友,因为我设置只要超过3个好友,就需要动态开辟,那么下次一打开就需要开辟空间,所以初始化中就需要判断是否满员
//2. 下一次打开我将文件中的信息在通讯录中展现,从文件中读二进制读到什么时候就可以停了
{
	FILE* pf = (FILE*)fopen("text", "rb");
	if (pf == NULL)
	{
		printf("LoadContact:%s\n", strerror(errno));
		return;
	}
	struct Peopleinformation tmp = { 0 };
	while (fread(&tmp, sizeof(struct Peopleinformation), 1, pf))//解决第二个问题,什么时候读文件停止
		//fread函数的返回值为0时,表示文件内容已经读完了,不需要再读文件了;返回1表示我读到一个元素,就把他放到通讯录里
	{
		//解决第一个问题,判断是否满员,满员就增容
		if (ps->size == ps->capacity)//如果已经加上的好友个数等于通讯录的最大容量,本程序设置是3
		{
			struct Peopleinformation* ptr = realloc(ps->data, (ps->capacity + 2)*sizeof(struct Peopleinformation));//realloc空间拓展到5个数组大小
			if (ptr != NULL)//判断是否拓展成功
			{
				ps->data = ptr;
				ps->capacity += 2;
				printf("增容成功\n");
			}
			ps->data[ps->size] = tmp;//ps->data表示找到数组总人数;ps->data[ps->size]表示指向有效的人数
			ps->size++;//通讯录中有效人数++
		}
	}
	fclose(pf);
	pf = NULL;
}
void InitContact(struct Contact* ps)//初始化通讯录
{
	ps->data = (struct Peopleinformation*)malloc(3 * sizeof(struct Peopleinformation));//malloc动态开辟3个结构体大小的空间
	if (ps->data == NULL)//判断是否开辟空间成功
	{
		return;//初始化函数的返回类型是void,所以直接return;就行
	}
	ps->capacity = 3;
	ps->size = 0;
	//我们希望在初始化的过程中把上一次修改过的通讯录保存下来,也就是下次打开通讯录能够显示上次加的好友,
	LoadContact(ps);
}

2.5 增加好友的功能函数

 
void Check_Capacity(Contact* pc)
{
	if (pc->sz == pc->capacity)//判断是否需要增容
	{
		//增容
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ)*sizeof(PeoInfo));
		if (ptr == NULL)
		{
			//增容失败
			perror("AddContact");
			printf("增容联系人失败\n");
			return;
		}
		else
		{
			//增容成功 
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("增容成功\n");
		}
	}
}
//增加联系人的信息 —— 动态
void AddContact(Contact* pc)
{
 
	//通讯录满员-> 增容
	Check_Capacity(pc);//一级指针传参,一级指针接收。
 
	//通讯录未满,可以添加新成员,增加一个人的信息
	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].addr);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->sz].tele);
	(pc->sz)++;
	printf("增加联系人员成功\n");
	//在这里,虽然[ ]的优先级高于->,,但是,data和[ ]是不可以先进行结合的,因为,这是在一个调用函数中,形参那部分接受到的只有指针变量pc
	//也就是说,如果后两者进行结合的话,系统根本就不知道data是什么东西,所以它结合出来是错误的,即,虽然[ ]的优先级高于->,但是后两者不能
	//进行结合会出错,所以,即使[]的优先级比较高,还是先让data和->进行结合,即先进行pc->data的操作,在结构体成员变量中找到了指针变量data,
	//又因为该指针变量data指向了由malloc函数在堆区上动态开辟的内存空间的起始位置的地址,相当于数组首元素的地址,在这里不是特例,所以,
	//就等价于找到了该数组的数组名,即,pc->data === 数组名, 知道了数组名,再通过数组下标进行访问数组中的元素。
}

2.6 显示好友的功能函数

static int FindByName(struct Contact* ps, char name[20])//static在此处的意义为每循环一次外部函数,上次查找过得名字不会再次被查找
{
	int i = 0;
	for (i = 0; i < ps->size; i++)//循环的范围时通讯录中已经添加的有效人员的个数
	{
		if (0 == strcmp(ps->data[i].name, name))//字符串比较函数,==0 表示相等的情况
		{//if判断语句的意思是结构体变量数组data中的名字和要查找的名字相同,我就返回该名字对应数组的下角标
			return i;
		}
	}
	return -1;//返回-1,表示两个不相等,也可以说是没有找到该人
}
void ShowContact(const struct Contact* ps)//const 它限定一个变量不允许被改变,产生静态作用。
{
	if (ps->size == 0)
	{
		printf("通讯录为空\n");//ps->size表示通讯录中的有效人数
	}
	else//通讯录目前是有好友的,显示出来也可以说是将通讯录中好友的信息打印出来
	{
		int i = 0;
		printf("%-5s\t%-4s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
		for (i = 0; i < ps->size; i++)//循环的次数为通讯录中具有有效信息的好友个数
		{
			printf("%-5s\t %-4d\t %-5s\t %-12s\t %-20s\n",
				ps->data[i].name,
				ps->data[i].age,
				ps->data[i].sex,
				ps->data[i].tel,
				ps->data[i].address);
		}
	}//for循环打印结构体信息
}
 

2.7 删除好友的功能函数

static int FindByName(struct Contact* ps, char name[20])//static在此处的意义为每循环一次外部函数,上次查找过得名字不会再次被查找
{
	int i = 0;
	for (i = 0; i < ps->size; i++)//循环的范围时通讯录中已经添加的有效人员的个数
	{
		if (0 == strcmp(ps->data[i].name, name))//字符串比较函数,==0 表示相等的情况
		{//if判断语句的意思是结构体变量数组data中的名字和要查找的名字相同,我就返回该名字对应数组的下角标
			return i;
		}
	}
	return -1;//返回-1,表示两个不相等,也可以说是没有找到该人
}
void DelContact(struct Contact* ps)
{
	char name[20];
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	int pos = FindByName(ps, name);//同样的,先通过外部函数找到所要找的人
	if (pos == -1)
	{
		printf("要删除的人不存在\n");//无
	}
	else
	{
		int j = 0;
		for (j = 0; j < ps->size - 1; j++)//之所以j < ps->size - 1;是因为ps->size是已经添加的有效人数
			//该代码的意思是将我举例子0 1 2 3 5 6 7 8 9 9中的最后一个9删除,打印时不访问最后一个元素,相当于把最后一个9删除了
		{
			ps->data[pos] = ps->data[j + 1];
			//该循环的意思是:假如数组中的成员为0 1 2 3 4 5 6 7 8 9,我想要删除4,该代码的意思是我用5覆盖4,6覆盖5
			//7覆盖6,8覆盖7,9覆盖8,这样数组会变成0 1 2 3 5 6 7 8 9 9,成功达到了删除4的目的,并且没有改变原数组中其他元素的顺序
		}
		ps->size--;//通讯录有效人数随循环次数--
		printf("删除成功\n");
	}
}
 

2.8 查找好友的功能函数

static int FindByName(struct Contact* ps, char name[20])//static在此处的意义为每循环一次外部函数,上次查找过得名字不会再次被查找
{
	int i = 0;
	for (i = 0; i < ps->size; i++)//循环的范围时通讯录中已经添加的有效人员的个数
	{
		if (0 == strcmp(ps->data[i].name, name))//字符串比较函数,==0 表示相等的情况
		{//if判断语句的意思是结构体变量数组data中的名字和要查找的名字相同,我就返回该名字对应数组的下角标
			return i;
		}
	}
	return -1;//返回-1,表示两个不相等,也可以说是没有找到该人
}
void SearchContact(struct Contact* ps)//结构体指针接收传址调用的地址
{
	char name[20];
	printf("请输入要查找人的名字\n");
	scanf("%s", name);
	int pos = FindByName(ps, name);//通过外部函数的返回值查找到想要找到的人
	if (pos == -1)
	{
		printf("要查找的人不存在\n");//无
	}
	else
	{//找到了,打印出该人的信息
		printf("%-5s\t%-4s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
		printf("%-5s\t %-4d\t %-5s\t %-12s\t %-20s\n",
			ps->data[pos].name,
			ps->data[pos].age,
			ps->data[pos].sex,
			ps->data[pos].tel,
			ps->data[pos].address);
	}//%s 打印字符,%d打印整型,%-5s\t表示对齐
	//"\t"在C语言里表示水平制表(HT) (跳到下一个TAB位置)
}
 

2.9 修改好友的功能函数

static int FindByName(struct Contact* ps, char name[20])//static在此处的意义为每循环一次外部函数,上次查找过得名字不会再次被查找
{
	int i = 0;
	for (i = 0; i < ps->size; i++)//循环的范围时通讯录中已经添加的有效人员的个数
	{
		if (0 == strcmp(ps->data[i].name, name))//字符串比较函数,==0 表示相等的情况
		{//if判断语句的意思是结构体变量数组data中的名字和要查找的名字相同,我就返回该名字对应数组的下角标
			return i;
		}
	}
	return -1;//返回-1,表示两个不相等,也可以说是没有找到该人
}
void ModifyContact(struct Contact* ps)//传址调用通过结构体指针来接收
{
	char name[20];//通过名字找到所要修改人的信息
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	int pos = FindByName(ps, name);//定义外部函数
	if (pos == -1)
	{
		printf("要修改人的信息不存在\n");//找不到该人
	}
	else
	{//如果找到该人,则通过外部函数的返回值找到该名字在数组中对应的下角标,并且修改该人的信息
		printf("请输入名字:>");
		scanf("%s", ps->data[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(ps->data[pos].age));
		printf("请输入性别:>");
		scanf("%s", ps->data[pos].sex);
		printf("请输入电话:>");
		scanf("%s", ps->data[pos].tel);
		printf("请输入地址:>");
		scanf("%s", ps->data[pos].address);
		printf("修改完成\n");
	}
}
 

2.10 排序好友的功能函数

qsort冒泡排序函数,函数定义:void qsort(void* base,size_t num,size_t size,int(*compar)(const void*,const void*))

void* base:首元素的地址;size_t num:待排序的数据个数;size_t size:所占字节的大小;int(*compar)(const void*,const void*):比较两个数据的大小;

enum Option_qsort
{
	exit_sort,//0
	name,//1
	age,//2
	sex,//3
	address,//4
	tel//5
};
void menu_qsort()
{
	printf("************************************\n");
	printf("****** 1. name   2. age       ******\n");
	printf("****** 3. sex    4. address   ******\n");
	printf("****** 5. tel    0. exit_sort ******\n");
	printf("************************************\n");
}
int compare_tel(const void*e1, const void*e2)
{
	return strcmp(((struct Peopleinformation*)e1)->tel, ((struct Peopleinformation*)e2)->tel);
}
int compare_address(const void*e1, const void*e2)
{
	return strcmp(((struct Peopleinformation*)e1)->address, ((struct Peopleinformation*)e2)->address);
}
int compare_sex(const void*e1, const void*e2)
{
	return strcmp(((struct Peopleinformation*)e1)->sex, ((struct Peopleinformation*)e2)->sex);
}
int compare_age(const void*e1, const void*e2)
{
	return strcmp(((struct Peopleinformation*)e1)->age, ((struct Peopleinformation*)e2)->age);
}
int compare_name(const void*e1, const void*e2)
{
	return strcmp(((struct Peopleinformation*)e1)->name, ((struct Peopleinformation*)e2)->name);
}
void print(struct Contact* ps)
{
	int i = 0;
		printf("%-5s\t%-4s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
		for (i = 0; i < ps->size; i++)
		{
			printf("%-5s\t %-4d\t %-5s\t %-12s\t %-20s\n",
				ps->data[i].name,
				ps->data[i].age,
				ps->data[i].sex,
				ps->data[i].tel,
				ps->data[i].address);
		}
}
void SortContact(struct Contact* ps)
{//通讯录排序仿照main函数来进行;
	int input = 0;
	do
	{
		menu_qsort();//打印排序的菜单方式
		printf("请选择排序的方式:>");
		scanf("%d", &input);
		switch (input)
		{
		case name://按照名字排序
			qsort(ps->data, ps->size, sizeof(ps->data[0]), compare_name);
			print(ps);//打印排序以后的个人信息
			break;
		case age://按照年龄排序
			qsort(ps->data, ps->size, sizeof(ps->data[0]), compare_age);
			print(ps);
			break;
		case sex://按照性别排序
			qsort(ps->data, ps->size, sizeof(ps->data[0]), compare_sex);
			print(ps);
			break;
		case address://按照住址排序
			qsort(ps->data, ps->size, sizeof(ps->data[0]), compare_address);
			print(ps);
			break;
		case tel://按照电话排序
			qsort(ps->data, ps->size, sizeof(ps->data[0]), compare_tel);
			print(ps);
			break;
		case exit_sort://离开排序功能
			printf("通讯录排序功能退出成功\n");
			printf("\n");
			break;
		default:
			printf("选择排序的方式错误,请重新选择:>");
			break;
		}
	} while (input);
}
 

2.11 清除好友的功能函数

void ClearContact(struct Contact* ps)
{
	(ps->size) = 0;
	memset(ps->data, 0, sizeof(ps->data));
	printf("清空成功\n");
	printf("\n");
}//清空所有联系人的函数很好理解,用memset内存设置函数,将数组data设置为0,通讯录中有效人数设置为0

2.12 摧毁通讯录的功能函数

void DestroyContact(struct Contact* ps)
{
	free(ps->data);//释放空间
	ps->data = NULL;//将指针赋值为NULL
	ps->size = 0;//通讯录上已经添加的好友清0
	ps->capacity = 0;//通讯录的可容纳的容量清0
}

2.13 保存通讯录的功能函数

void SaveContact(struct Contact* ps)
{
	FILE* pf = (FILE*)fopen("text", "wb");//以二进制的形式写入文件
	if (pf == NULL)
	{
		printf("SaveContact:%s\n", strerror(errno));//SaveContact:%s\n方便判断错误是哪里出现的
		return;
	}
	int i = 0;
	for (i = 0; i < ps->size; i++)//for循环在已经确定的好友容量内循环
	{
		fwrite(&(ps->data[i]), sizeof(struct Peopleinformation), 1, pf);//每循环一次,写入文件的好友容量加1
	}//&(ps->data[i])表示data数组中下标为i的好友,循环一次,将一个好友写入文件
	//&(ps->data[i])等价于ps->data+i(指针本身就指向地址)
	fclose(pf);
	pf = NULL;
}

3. 总的程序代码

该代码与上述模块的代码功能有些许差异

3.1 main.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

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

int main()
{
	int input = 0;
	//创建通讯录
	struct Contact con;//con就是通讯录,里边包含:data指针和size,capacity
	//初始化通讯录
	InitContact(&con);
	//
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SEARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			//自主实现
			SortContact(&con);
			break;
		case EXIT:
			//销毁通讯录-释放动态开辟的内存
			SaveContact(&con);
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
		case SAVE:
			SaveContact(&con);
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

3.2 contact.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "contact.h"

void InitContact(struct Contact* ps)
{
	ps->data = (struct PeoInfo*)malloc(DEFAULT_SZ*sizeof(struct PeoInfo));
	if(ps->data == NULL)
	{
		return;
	}
	ps->size = 0;
	ps->capacity = DEFAULT_SZ;
	//把文件中已经存放的通讯录中的信息加载到通讯录中
	LoadContact(ps);
}

//声明函数
void CheckCapacity(struct Contact* ps);

void LoadContact(Contact* ps)
{
	PeoInfo tmp = { 0 };
	FILE* pfRead = fopen("contact.dat", "rb");
	if (pfRead == NULL)
	{
		printf("LoadContact::%s\n", strerror(errno));
		return;
	}
	
	//读取文件,存放到通讯录中
	while (fread(&tmp, sizeof(PeoInfo), 1, pfRead))
	{
		CheckCapacity(ps);
		ps->data[ps->size] = tmp;
		ps->size++;
	}

	fclose(pfRead);
	pfRead = NULL;
}
void CheckCapacity(struct Contact* ps)
{
	if(ps->size == ps->capacity)
	{
		//增容
		struct PeoInfo* ptr = realloc(ps->data, (ps->capacity+2)*sizeof(PeoInfo));
		if(ptr != NULL)
		{
			ps->data = ptr;
			ps->capacity += 2;
			printf("增容成功\n");
		}
		else
		{
			printf("增容失败\n");
		}
	}
}

void AddContact(struct Contact* ps)
{
	//检测当前通讯录的容量
	//1. 如果满了,就增加空间
	//2. 如果不满,啥事都不干
	CheckCapacity(ps);
	//增加数据
	printf("请输入名字:>");
	scanf("%s", ps->data[ps->size].name);
	printf("请输入年龄:>");
	scanf("%d", &(ps->data[ps->size].age));
	printf("请输入性别:>");
	scanf("%s", ps->data[ps->size].sex);
	printf("请输入电话:>");
	scanf("%s", ps->data[ps->size].tele);
	printf("请输入地址:>");
	scanf("%s", ps->data[ps->size].addr);

	ps->size++;
	printf("添加成功\n");
}

void ShowContact(const struct Contact* ps)
{
	if (ps->size == 0)
	{
		printf("通讯录为空格\n");
	}
	else
	{
		int i = 0;
		//标题
		printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
		//数据
		for (i = 0; i < ps->size; i++)
		{
			printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
				ps->data[i].name,
				ps->data[i].age,
				ps->data[i].sex,
				ps->data[i].tele,
				ps->data[i].addr);
		}
	}
}

static int FindByName(const struct Contact* ps, char name[MAX_NAME])
{
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		if (0 == strcmp(ps->data[i].name, name))
		{
			return i;
		}
	}

	return -1;//找不到的情况
}

void DelContact(struct Contact* ps)
{
	char name[MAX_NAME];
	int pos = 0;
	printf("请输入要删除人的名字:>");
	scanf("%s", name);
	//1. 查找要删除的人在什么位置
	//找到了返回名字所在元素的下标
	//找不到返回 -1
	pos = FindByName(ps, name);
	//2. 删除
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
	}
	else
	{
		//删除数据
		int j = 0;
		for (j = pos; j < ps->size-1; j++)
		{
			ps->data[j] = ps->data[j + 1];
		}
		ps->size--;
		printf("删除成功\n");
	}
}

void SearchContact(const struct Contact* ps)
{
	int pos = 0;
	char name[MAX_NAME];
	printf("请输入要查找人的名字:>");
	scanf("%s", name);
	pos = FindByName(ps, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
	}
	else
	{
		printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "电话", "地址");
		printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
			ps->data[pos].name,
			ps->data[pos].age,
			ps->data[pos].sex,
			ps->data[pos].tele,
			ps->data[pos].addr);
	}
}

void ModifyContact(struct Contact* ps)
{
	int pos = 0;
	char name[MAX_NAME];
	printf("请输入要修改人的名字:>");
	scanf("%s", name);
	pos = FindByName(ps, name);
	if (pos == -1)
	{
		printf("要修改人的信息不错在\n");
	}
	else
	{
		printf("请输入名字:>");
		scanf("%s", ps->data[pos].name);
		printf("请输入年龄:>");
		scanf("%d", &(ps->data[pos].age));
		printf("请输入性别:>");
		scanf("%s", ps->data[pos].sex);
		printf("请输入电话:>");
		scanf("%s", ps->data[pos].tele);
		printf("请输入地址:>");
		scanf("%s", ps->data[pos].addr);

		printf("修改完成\n");
	}
}

void SortContact(struct Contact*ps)
{

}

void DestroyContact(Contact* ps)
{
	free(ps->data);
	ps->data = NULL;
}

void SaveContact(Contact* ps)
{
	FILE* pfWrite = fopen("contact.dat", "wb");
	if (pfWrite == NULL)
	{
		printf("SaveContact::%s\n", strerror(errno));
		return;
	}
	//写通讯录中数据到为文件中
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		fwrite(&(ps->data[i]), sizeof(PeoInfo), 1, pfWrite);
	}

	fclose(pfWrite);
	pfWrite = NULL;
}

3.3 contact.h

#define _CRT_SECURE_NO_WARNINGS 1

//#define MAX 1000

#define DEFAULT_SZ 3


#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

enum Option
{
	EXIT,//0
	ADD, //1
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	SAVE
};

typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_ADDR];
}PeoInfo;

//通讯录类型
typedef struct Contact
{
	struct PeoInfo *data;//存放1000个信息
	int size;//记录当前已经有的元素个数
	int capacity;//当前通讯录的最大容量
}Contact;



//声明函数
//初始化通讯录的函数
void InitContact(struct Contact* ps);

//增加一个信息到通讯录
void AddContact(struct Contact* ps);

//打印通讯录中的信息
void ShowContact(const struct Contact* ps);

//删除指定的联系人
void DelContact(struct Contact* ps);

//查找指定的人的信息
void SearchContact(const struct Contact* ps);

//修改指定联系人
void ModifyContact(struct Contact* ps);

//排序通讯录内容
void SortContact(struct Contact*ps);

void DestroyContact(Contact* ps);

//保存文件
void SaveContact(Contact* ps);

//加载文件中的信息到通讯录
void LoadContact(Contact* ps);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值