通讯录管理系统(C语言版)

通讯录管理系统:

  • 一:静态版本
    • 1.通讯录前期准备
      • (1)菜单函数的实现
      • (2)菜单的功能
      • (3)关于联系人结构体的创建
      • (4)全局变量的定义
    • 2.通讯录的功能实现
      • (1)初始化通讯录
      • (2)添加联系人
      • (3)删除联系人
      • (4)查找联系人
      • (4)修改联系人
      • (5)显示联系人
      • (6)对通讯录中联系人的信息进行排序
    • 3. 代码呈现(分文件呈现)
      • (1)test.c
      • (2)contact.h
      • (3)contact.c
  • 二:动态版本
    • 1.动态版本的一些改变
      • (1)ccontact.h
      • (2)contact.c
  • 三:文件操作版本
    • 1.文件版本的改变
      • (1)主函数实现
      • (2)初始化功能实现
      • (3)保存通讯录中的信息
    • 2.代码的呈现
      • (1)test.c
      • (2)contact.h
      • (3)contact.c

一:静态版本

1.通讯录前期准备

(1)菜单函数的实现

1.先实现菜单函数,能够实现与用户的交互。
代码如下:

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

(2)菜单的功能

1.用switch选择语句来实现各自的功能
代码如下:

do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);     //增加
			break;
		case 2:
			DelContact(&con);      //删除
			break;
		case 3:
			SearchContact(&con);   //查找
			break;
		case 4:
			ModifyContact(&con);   //修改
			break;
		case 5:
			ShowContact(&con);     //显示
			break;
		case 6:
			SortContact(&con);     //排序
			break;
		default:
			printf("选择错误");
			break;
		}
	} while (input);
	return 0;

(3)关于联系人结构体的创建

1.结构体的创建
第一个结构体PeoInfo是是用来存放人的信息,第二个结构体Contact是通讯录的信息,data是以第一个结构体为类型的数组,count用来记录当前通讯录中实际的人数。

//类型的声明
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_DDR];
}PeoInfo;

//通讯录
typedef struct Contact
{
	PeoInfo data[100];//存放人的信息
	int count;//记录当前通讯录中的实际人的个数
} Contact;

(4)全局变量的定义

1.利用宏定义处理
代码如下:

#define MAX 100	     //总人数的大小
#define MAX_NAME 20  // 名字的长度
#define MAX_SEX 10	 //性别的长度
#define MAX_TELE 12	 //电话号码的长度
#define MAX_DDR 30	 //地址的长度

2.通讯录的功能实现

(1)初始化通讯录

这里用到memset函数,要包含含有string.h的头文件。
1.代码如下:

void InitContact(Contact* pc)
{	 
	//初始化结构体
	pc->count = 0;
	memset(pc->data, 0, sizeof(pc->data)); //长度为pc->data
}

(2)添加联系人

void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->count == MAX)
	{
		printf("通讯录已满,无法添加\n");
		return;
	}
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->count].age));//注意: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");
}

测试结果如下:
通讯录管理系统(C语言版)_第1张图片

(3)删除联系人

1,。先查找,再删除。

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	assert(pc);
	int i = 0;
	if (pc->count == 0)
	{
		printf("通讯录为空,没有信息可以删除\n");
		return ;
	}
	printf("请输入要删除的名字\n");				     
	scanf("%s", name);
	//删除
	//1.查找
	int pos=FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
		return;
	}
	//2.删除
	for (i = pos; i < pc->count-1; i++)//100-1
	{
		pc->data[i] = pc-> data[i + 1];	//后边元素往前覆盖
	}	
	pc->count--;
	printf("删除成功");
}

测试结果如下:
通讯录管理系统(C语言版)_第2张图片

(4)查找联系人

这里需要构建一个函数FindByName,如果找到名字,就返回i,否则返回-1。

static int FindByName(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void SearchContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的名字\n");
	scanf("%s", name);
	//1.查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	else
	//2打印
	{
		int i = 0;
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		for (i = 0; i < pc->count; i++)
		{
			printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,
														pc->data[i].age,
														pc->data[i].sex,
														pc->data[i].tele,
														pc->data[i].addr);
		}
	}
}

测试结构如下:
通讯录管理系统(C语言版)_第3张图片

(4)修改联系人

void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的名字:>\n");
	scanf("%s", name);
	//1.查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return  ;
	}
	printf("要修改的人的信息已经查找到,接下来开始修改");
	//2.修改
	printf("请输入名字:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));//注意:age要传地址加上&
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);

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

测试结果如下:
通讯录管理系统(C语言版)_第4张图片

(5)显示联系人

遍历,打印每一个元素即可。

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

测试代码如下:
通讯录管理系统(C语言版)_第5张图片

(6)对通讯录中联系人的信息进行排序

与冒泡排序差不多,如果只对名字来排序,就是比较首字母的大小。

int cmp_peo_by_name(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);

}
														   
void SortContact(Contact* pc)
{
	assert(pc);	//void qsort(void* base, size_t nitems, size_t size, int (*compar)(const void*, const void*))
	qsort(pc->data, pc->count,sizeof(PeoInfo), cmp_peo_by_name);
	printf("排序成功");
}
或者排序也可以为:
void SortContact(Contact* pc)
{
	if (pc->count == 0)
	{
		printf("通讯录中没有联系人");
	}
	else
	{
		for (int i = 0; i < pc->count - 1; i++)
		{
			for (int j = 0; j < pc->count-i-1; j++)
			{
				if ((strcmp(pc->data[j].name, pc->data[j + 1].name)) > 0)
				{
					PeoInfo tmp = pc->data[j];
					pc->data[j] = pc->data[j+1];
					pc->data[j + 1] = tmp;
				}

			}
		}
		printf("排序成功\n");
	}
}	

测试结果如下:
通讯录管理系统(C语言版)_第6张图片

3. 代码呈现(分文件呈现)

(1)test.c

#define _CRT_SECURE_NO_WARNINGS
#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("******   0.exit                 *********\n");
	printf("*****************************************\n");
}
int main()
{
	int input = 0;	 
	Contact con;//通讯录

	//初始化通讯录
	InitContact(&con);//

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			DelContact(&con);
			break;
		case 3:
			SearchContact(&con);
			break;
		case 4:
			ModifyContact(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			SortContact(&con);
			break;
		default:
			printf("选择错误");
			break;
		}
	} while (input);
	return 0;
}

(2)contact.h

#pragma once
#include 
#include 
#include "contact.h"
#include 
#include
#define MAX 100	     //总人数的大小
#define MAX_NAME 20  // 名字的长度
#define MAX_SEX 10	 //性别的长度
#define MAX_TELE 12	 //电话号码的长度
#define MAX_DDR 30	 //地址的长度

//类型的声明
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_DDR];
}PeoInfo;

//通讯录
typedef struct Contact
{
	PeoInfo data[100];//存放人的信息
	int count;//记录当前通讯录中的实际人的个数
} Contact;

//初始化通讯录
void InitContact(Contact* pc);

//增加联系人通讯录
void AddContact(Contact* pc);

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

//删除指定联系人
void DelContact(Contact* pc);

//查找联系人
void SearchContact(Contact* pc);

//修改联系人
void ModifyContact(Contact* pc);

//排序通信录中的内容(按照名字排序)
void SortContact(Contact* pc);

(3)contact.c

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
//1.静态版本
//2.动态版本
//3.文件的版本

void InitContact(Contact* pc)
{	 
	//初始化结构体
	pc->count = 0;
	memset(pc->data, 0, sizeof(pc->data));	//长度为pc->data
}

void AddContact(Contact* pc)
{
	assert(pc);
	if (pc->count == MAX)
	{
		printf("通讯录已满,无法添加\n");
		return;
	}
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->count].age));//注意: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 ShowContact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n",pc->data[i].name,
											 pc->data[i].age,
											 pc->data[i].sex,
											 pc->data[i].tele,
											 pc->data[i].addr);
	}
}

static int FindByName(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	assert(pc);
	int i = 0;
	if (pc->count == 0)
	{
		printf("通讯录为空,没有信息可以删除\n");
		return ;
	}
	printf("请输入要删除的名字:>\n");				     
	scanf("%s", name);
	//删除
	//1.查找
	int pos=FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
	}
	else
	{
	  	//2.删除
		for (i = pos; i < pc->count - 1; i++)//100-1
		{
		   pc->data[i] = pc-> data[i + 1];	//后边元素往前覆盖
		}
		pc->count--;
		printf("删除成功\n");
	}
}

void SearchContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的名字:>\n");
	scanf("%s", name);
	//1.查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	else
	//2打印
	{
		int i = 0;
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		for (i = 0; i < pc->count; i++)
		{
			printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,
														pc->data[i].age,
														pc->data[i].sex,
														pc->data[i].tele,
														pc->data[i].addr);
		}
	}
}

void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的名字:>\n");
	scanf("%s", name);
	//1.查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return  ;
	}
	printf("要修改的人的信息已经查找到,接下来开始修改");
	//2.修改
	printf("请输入名字:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));//注意:age要传地址加上&
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);

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

//int cmp_peo_by_name(const void* e1, const void* e2)
//{
//	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
//
//}
//														   
//void SortContact(Contact* pc)
//{
//	assert(pc);	//void qsort(void* base, size_t nitems, size_t size, int (*compar)(const void*, const void*))
//	qsort(pc->data, pc->count,sizeof(PeoInfo), cmp_peo_by_name);
//	printf("排序成功");
//}

//或者排序也可以为:
void SortContact(Contact* pc)
{
	if (pc->count == 0)
	{
		printf("通讯录中没有联系人");
	}
	else
	{
		for (int i = 0; i < pc->count - 1; i++)
		{
			for (int j = 0; j < pc->count-i-1; j++)
			{
				if ((strcmp(pc->data[j].name, pc->data[j + 1].name)) > 0)
				{
					PeoInfo tmp = pc->data[j];
					pc->data[j] = pc->data[j+1];
					pc->data[j + 1] = tmp;
				}

			}
		}
		printf("排序成功\n");
	}
}

二:动态版本

1.动态版本的一些改变

1.相较于静态的实现,两者的差别并不大,前者是用一个固定数组来实现元素的,储存后者则是用动态申请的内存来实现储存,优点是可以节省内存区别在于通讯录的初始化,这里引用了capcity容量来比较已有的容量来判断内存的使用量,便于扩容其次就是Add函数,增加联系人最后再对释放的内存进行释放。所以以下的部分代码是有区别的。

(1)ccontact.h

//动态版本:
#pragma once
#include 
#include 
#include "contact.h"
#include 
#include
#define DEFAULT_SZ 3
#define INC_SZ	2  //增长的个数2
#define MAX 100	     //总人数的大小
#define MAX_NAME 20  // 名字的长度
#define MAX_SEX 10	 //性别的长度
#define MAX_TELE 12	 //电话号码的长度
#define MAX_DDR 30	 //地址的长度
	
//类型的声明
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_DDR];
}PeoInfo;
//动态版本:
typedef struct Contact
{
	PeoInfo* data;//存放人的信息,用指针
	int count;//记录当前通讯录中的实际人的个数
	int capacity;//当前通讯录的容量
} Contact;


//初始化通讯录
int InitContact(Contact* pc);

//销毁通讯录
void DestoryContact(Contact* pc);

//增加联系人通讯录
void AddContact(Contact* pc);

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

//删除指定联系人
void DelContact(Contact* pc);

//查找联系人
void SearchContact(Contact* pc);

//修改联系人
void ModifyContact(Contact* pc);

//排序通信录中的内容(按照名字排序)
void SortContact(Contact* pc);

//增容
void CheckCapacity(Contact* pc);


(2)contact.c

//动态版本:
int InitContact(Contact* pc)	//返回类型改为int
{
	assert(pc);
	pc->count = 0;
	pc->data = (PeoInfo*)calloc(DEFAULT_SZ,sizeof(PeoInfo));//三个
	if (pc->data == NULL)
	{
		printf("InitContact::%s\n", strerror(errno));
		return 1;
	}
	pc->capacity = DEFAULT_SZ;
	return 0;
}
//动态版本:
void CheckCapacity(Contact* pc)
{
	if (pc->count == pc->capacity)		 //(总容量+新增长的空间的个数)*一个元素的大小
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			printf("AddContact::%s\n", strerror(errno));
			return;
		}
		else
		{
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("增容成功\n");
		}
	}
}

void DestoryContact(Contact* pc)
{
	assert(pc);
	free(pc->data);
	pc->data = NULL;
}

void AddContact(Contact* pc)
{
	assert(pc);
	//增容
	CheckCapacity(pc);
	//
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->count].age));//注意: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 ShowContact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n",pc->data[i].name,
											 pc->data[i].age,
											 pc->data[i].sex,
											 pc->data[i].tele,
											 pc->data[i].addr);
	}
}

static int FindByName(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	assert(pc);
	int i = 0;
	if (pc->count == 0)
	{
		printf("通讯录为空,没有信息可以删除\n");
		return ;
	}
	printf("请输入要删除的名字:>\n");				     
	scanf("%s", name);
	//删除
	//1.查找
	int pos=FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
	}
	else
	{
	  	//2.删除
		for (i = pos; i < pc->count - 1; i++)//100-1
		{
		   pc->data[i] = pc-> data[i + 1];	//后边元素往前覆盖
		}
		pc->count--;
		printf("删除成功\n");
	}
}

void SearchContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的名字:>\n");
	scanf("%s", name);
	//1.查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	else
	//2打印
	{
		int i = 0;
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		for (i = 0; i < pc->count; i++)
		{
			printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,
														pc->data[i].age,
														pc->data[i].sex,
														pc->data[i].tele,
														pc->data[i].addr);
		}
	}
}

void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的名字:>\n");
	scanf("%s", name);
	//1.查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return  ;
	}
	printf("要修改的人的信息已经查找到,接下来开始修改");
	//2.修改
	printf("请输入名字:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));//注意:age要传地址加上&
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);

	printf("修改成功\n");
}
//或者排序也可以为:
void SortContact(Contact* pc)
{
	if (pc->count == 0)
	{
		printf("通讯录中没有联系人");
	}
	else
	{
		for (int i = 0; i < pc->count - 1; i++)
		{
			for (int j = 0; j < pc->count-i-1; j++)
			{
				if ((strcmp(pc->data[j].name, pc->data[j + 1].name)) > 0)
				{
					PeoInfo tmp = pc->data[j];
					pc->data[j] = pc->data[j+1];
					pc->data[j + 1] = tmp;
				}

			}
		}
		printf("排序成功\n");
	}
}

三:文件操作版本

1.文件版本的改变

(1)主函数实现

1.该版本创建通讯录的时候,此处创建的是一个结构体变量con,建立的是一个结构体数组,此处结构体变量中存储的一方面有通讯录中所有人的信息即data,这些信息打包成了一个数组,同时还有两个整型变量,size存储的是当前已经有的元素个数,而capacity存储的是当前通讯录的最大容量。相比之前的动态管理版本,此处增加了保存选项,同时在退出通讯录之前都会默认进行一次保存,以防用户在退出之前对通讯录的信息忘记进行保存。
代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
int main()
{
	int input = 0;	 
	Contact con;//通讯录

	//初始化通讯录
	InitContact(&con);//

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SRARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case EXIT:
			SaveContact(&con);
			DestoryContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

(2)初始化功能实现

1.此处增加了一个LoadContact()函数,是将之前文件中联系人的信息加载到通讯录中来,使用了文件操作函数fread()函数来对文件中的信息进行读取,每次读一个数据。
注意:当动态开辟的空间不够时,要使用CheckCapacity()函数对容量进行检查,如果容量不够就要进行扩容。

//加载文件中的信息到通讯录
void LoadContact(Contact* pc)
{
	FILE* pfRead = fopen("contact.txt", "rb");
	if(pfRead==NULL)
	{
		perror("LoadContact");
		return;				  
	}
	PeoInfo tmp = { 0 };																	   

while(fread(&tmp, sizeof(PeoInfo), 1, pfRead) == 1)
{
	//判断容量,是否需要扩容
	CheckCapacity(pc);

	pc->data[pc->count] = tmp;	  // 一个一个放
	pc->count++;
}

	fclose(pfRead);
	pfRead = NULL;
 }
 
int InitContact(Contact* pc)	//返回类型改为int
{
	assert(pc);
	pc->count = 0;
	pc->data = (PeoInfo*)calloc(DEFAULT_SZ,sizeof(PeoInfo));//三个
	if (pc->data == NULL)
	{
		printf("InitContact::%s\n", strerror(errno));
		return 1;
	}
	pc->capacity = DEFAULT_SZ;
	//加载文件的信息到通讯录中
	LoadContact(pc);

	return 0;
}

(3)保存通讯录中的信息

1.保存通讯录中的信息,使用的是fwrite()函数,即将通讯录中的数据写入到文件中去,同时使用了fopen()和fclose()进行关闭文件。最后要将文件指针置为空指针。

void SaveContact(const Contact* pc)
{
	assert(pc);
	FILE* pfWrite = fopen("contact.txt","wb");
	if (pfWrite == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写文件 二进制的形式
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{							    //size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pfWrite);//把ptr所指向的数组中的数据写入到给定的stream.
	}
	fclose(pfWrite);					   
	pfWrite = NULL;
}	

2.代码的呈现

(1)test.c

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"

//设置枚举类型
enum Option
{
	EXIT,
	ADD,
	DEL,
	SRARCH,
	MODIFY,
	SHOW,
	SORT
};

void menu()
{																			
	printf("*****************************************\n");
	printf("******   1.add        2.del     *********\n");
	printf("******   3.search     4.modify  *********\n");
	printf("******   5.show       6.sort    *********\n");
	printf("******   0.exit                 *********\n");
	printf("*****************************************\n");
}
int main()
{
	int input = 0;	 
	Contact con;//通讯录

	//初始化通讯录
	InitContact(&con);//

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			break;
		case DEL:
			DelContact(&con);
			break;
		case SRARCH:
			SearchContact(&con);
			break;
		case MODIFY:
			ModifyContact(&con);
			break;
		case SHOW:
			ShowContact(&con);
			break;
		case SORT:
			SortContact(&con);
			break;
		case EXIT:
			SaveContact(&con);
			DestoryContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;

}

(2)contact.h

#pragma once
#include 
#include 
#include "contact.h"
#include 
#include
#define DEFAULT_SZ 3
#define INC_SZ	2  //增长的个数2
#define MAX 100	     //总人数的大小
#define MAX_NAME 20  // 名字的长度
#define MAX_SEX 10	 //性别的长度
#define MAX_TELE 12	 //电话号码的长度
#define MAX_DDR 30	 //地址的长度

//类型的声明
typedef struct PeoInfo
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELE];
	char addr[MAX_DDR];
}PeoInfo;

//动态版本:
typedef struct Contact
{
	PeoInfo* data;//存放人的信息,用指针
	int count;//记录当前通讯录中的实际人的个数
	int capacity;//当前通讯录的容量
} Contact;

//初始化通讯录
int InitContact(Contact* pc);

//销毁通讯录
void DestoryContact(Contact* pc);

//增加联系人通讯录
void AddContact(Contact* pc);

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

//删除指定联系人
void DelContact(Contact* pc);

//查找联系人
void SearchContact(Contact* pc);

//修改联系人
void ModifyContact(Contact* pc);

//排序通信录中的内容(按照名字排序)
void SortContact(Contact* pc);

//增容
void CheckCapacity(Contact* pc);

//保存通讯录
void SaveContact(const Contact* pc);

//加载文件的通讯录
	
void LoadContact(Contact* pc);

(3)contact.c

#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
//加载文件中的信息到通讯录
void LoadContact(Contact* pc)
{
	FILE* pfRead = fopen("contact.txt", "rb");
	if(pfRead==NULL)
	{
		perror("LoadContact");
		return;				  
	}
	PeoInfo tmp = { 0 };
																	   
while(fread(&tmp, sizeof(PeoInfo), 1, pfRead) == 1)
{
	//判断容量,是否需要扩容
	CheckCapacity(pc);

	pc->data[pc->count] = tmp;	  // 一个一个放
	pc->count++;
}
	fclose(pfRead);
	pfRead = NULL;
 }

//初始化:
int InitContact(Contact* pc)	//返回类型改为int
{
	assert(pc);
	pc->count = 0;
	pc->data = (PeoInfo*)calloc(DEFAULT_SZ,sizeof(PeoInfo));//三个
	if (pc->data == NULL)
	{
		printf("InitContact::%s\n", strerror(errno));
		return 1;
	}
	pc->capacity = DEFAULT_SZ;
	//加载文件的信息到通讯录中
	LoadContact(pc);
	
	return 0;
}
//增容
void CheckCapacity(Contact* pc)
{
	if (pc->count == pc->capacity)		 //(总容量+新增长的空间的个数)*一个元素的大小
	{
		PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			printf("AddContact::%s\n", strerror(errno));
			return;
		}
		else
		{
			pc->data = ptr;
			pc->capacity += INC_SZ;
			printf("增容成功\n");
		}
	}
}

void DestoryContact(Contact* pc)
{
	assert(pc);					  
	free(pc->data);
	pc->data = NULL;
}

void AddContact(Contact* pc)
{
	assert(pc);
	//增容
	CheckCapacity(pc);
	//
	printf("请输入名字:>");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pc->count].age));//注意: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 ShowContact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	for (i = 0; i < pc->count; i++)
	{
		printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n",pc->data[i].name,
											 pc->data[i].age,
											 pc->data[i].sex,
											 pc->data[i].tele,
											 pc->data[i].addr);
	}
}

static int FindByName(Contact* pc, char name[])
{
	assert(pc);
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;
}

void DelContact(Contact* pc)
{
	char name[MAX_NAME] = { 0 };
	assert(pc);
	int i = 0;
	if (pc->count == 0)
	{
		printf("通讯录为空,没有信息可以删除\n");
		return ;
	}
	printf("请输入要删除的名字:>\n");				     
	scanf("%s", name);
	//删除
	//1.查找
	int pos=FindByName(pc, name);
	if (pos == -1)
	{
		printf("要删除的人不存在\n");
	}
	else
	{
	  	//2.删除
		for (i = pos; i < pc->count - 1; i++)//100-1
		{
		   pc->data[i] = pc-> data[i + 1];	//后边元素往前覆盖
		}
		pc->count--;
		printf("删除成功\n");
	}
}

void SearchContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要查找的名字:>\n");
	scanf("%s", name);
	//1.查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要查找的人不存在\n");
		return;
	}
	else
	//2打印
	{
		int i = 0;
		printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		for (i = 0; i < pc->count; i++)
		{
			printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,
														pc->data[i].age,
														pc->data[i].sex,
														pc->data[i].tele,
														pc->data[i].addr);
		}
	}
}

void ModifyContact(Contact* pc)
{
	assert(pc);
	char name[MAX_NAME] = { 0 };
	printf("请输入要修改的名字:>\n");
	scanf("%s", name);
	//1.查找
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("要修改的人不存在\n");
		return  ;
	}
	printf("要修改的人的信息已经查找到,接下来开始修改");
	//2.修改
	printf("请输入名字:>");
	scanf("%s", pc->data[pos].name);
	printf("请输入年龄:>");
	scanf("%d", &(pc->data[pos].age));//注意:age要传地址加上&
	printf("请输入性别:>");
	scanf("%s", pc->data[pos].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pos].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pos].addr);

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

void SortContact(Contact* pc)
{
	if (pc->count == 0)
	{
		printf("通讯录中没有联系人");
	}
	else
	{													
		for (int i = 0; i < pc->count - 1; i++)
		{
			for (int j = 0; j < pc->count-i-1; j++)
			{
				if ((strcmp(pc->data[j].name, pc->data[j + 1].name)) > 0)
				{
					PeoInfo tmp = pc->data[j];
					pc->data[j] = pc->data[j+1];
					pc->data[j + 1] = tmp;
				}

			}
		}
		printf("排序成功\n");
	}
}

void SaveContact(const Contact* pc)
{
	assert(pc);
	FILE* pfWrite = fopen("contact.txt","wb");
	if (pfWrite == NULL)
	{
		perror("SaveContact");
		return;
	}
	//写文件 二进制的形式
	int i = 0;
	for (i = 0; i < pc->count; i++)
	{							    //size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
		fwrite(pc->data + i, sizeof(PeoInfo), 1, pfWrite);//把ptr所指向的数组中的数据写入到给定的stream.
	}
	fclose(pfWrite);					   
	pfWrite = NULL;
}													

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