有趣的代码——手机通讯录的简单实现

前面的文章中我们介绍了好几种小游戏,比如猜数字、井字棋、扫雷等等,这些都是我们实实在在通过自己的努力学习收获而来的,也是我们向非计算机专业同学“炫技”的好帮手。但是,这些东西,好像无法拿到一些家长面前和他们分享我们的成功和喜悦,因为部分家长可能会不太认可这些小玩意儿,所以,今天带着大家实现一个有用的、拿的出手的小程序——手机通讯录,希望大家能够从中有所收获,更希望你的付出和努力能够得到家长的认可和鼓励。

目录

1.手机通讯录的大致功能

2.手机通讯录的实现思路

3.手机通讯录各个部分的实现

3.1联系人变量的建立

3.2通讯录的建立

3.3通讯录的初始化

3.4通讯录的增容

3.5添加联系人

3.6打印通讯录

3.7 判断联系人存在

3.8删除联系人

3.9查找联系人

3.10修改联系人信息

3.11保存联系人信息至文件

 3.12加载文件中联系人信息至程序

3.13销毁动态通讯录

4.手机通讯录的代码实现

4.1TongXunLu.c源文件的完整代码如下:

4.2contact.h头文件的完整代码如下:

4.3contact.c源文件的完整代码如下:


1.手机通讯录的大致功能

虽然随着社会的进步和科技的发展,传统的电话通讯逐渐被微信、QQ等新型通讯软件替代,但电话通讯目前仍是我们手机不可缺少的必备功能。而对于这种手机必备功能,相信大家对于其功能都不会陌生,至于我们今天要实现的手机通讯录简易版。

它有以下有些功能:

①添加联系人

②删除联系人

③打印通讯录

④查找联系人

⑤修改联系人

⑥分类联系人

⑦保存联系人信息至文件

 上述是今天简易实现的手机通讯录的全部功能,接下来让我们一步一步看如何实现吧!

2.手机通讯录的实现思路

还记得我在猜数字游戏的实现中说过的一句话吗?没错,我们在写编程题或者小游戏代码时,最重要的就是理清实现思路——主体是什么?为了实现目的要创建哪些函数?函数的功能都是什么?只有当我们心中有了一个大体的框架,知道该做些什么时,我们才能更高效地编写代码,完成程序设计。

手机通讯录的算法实现如下:

1.提供菜单并提示用户选择要进行的功能;

2.完成对应选项的功能;

3.再次提供菜单询问;

根据上面的简易思路,我们可以先写出大体的框架的代码,具体如下:

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;
	//创建通讯录
	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:
				break;
			case EXIT:
				//销毁通讯录-释放动态开辟的内存
				printf("请确认当前联系人信息已经保存,是否继续退出?\n1.YES		2.NO\n");
			    int select = 0;
			    scanf("%d", &select);
			    if (select == 2)
			    {
				    input = 1;
				    break;
			    }
			    else
			    {
				    DestroyContast(&con);
				    printf("退出通讯录\n");
				    break;
			    }
			case SAVE:
				SaveContact(&con);
				break;
			default:
				printf("选择错误\n");
				break;
		}
	}while(input);
	return 0;
}

上面的代码完成了通讯录的最基本功能——提供菜单,但是对于每一项具体功能没有给出实现代码,只是起了个名字放在哪里——我称之为空壳函数,那接下来我们就逐步实现这些函数即可。

3.手机通讯录各个部分的实现
3.1联系人变量的建立

对于每一位联系人,我们肯定要存储其很多相关信息,比如姓名、性别、年龄、电话、地址等等信息,而在已知C语言提供的数据类型中没有能够满足这样需求的,所以,我们就不难想到要定义结构体类型来存放联系人信息。

结构体类型定义代码如下图所示:

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

相信聪明的你能够轻易看出这里我们的联系人包含了姓名、年龄、性别、电话、地址这五项基本信息,当然大家也可以根据需求自行添加别的信息。

3.2通讯录的建立

既然是通讯录,我们肯定要存放很多联系人的信息,那么我们应该建立多大的数组呢?建立的太大,我们可能用不到,反而过多占用系统资源;建立的太少,又可能不够我们使用。为了避免上面两种情况的出现,我们这里建议使用动态开辟内存,这样就可以根据所需开辟空间,提高资源利用率。

代码如下所示:

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

 上面定义的结构体类型变量就是一个通讯录了,所以我们只需要定义一个结构体变量就是建立一个通讯录了。

3.3通讯录的初始化

这里并没有太多讲究,只是大家要记住要动态开辟空间。

初始化函数InitContact的代码如下:

void InitContact(struct Contact* ps)
{
	ps->data=(struct PeoInfo*)malloc(DEFAULT_SZ*sizeof(struct PeoInfo));
	if(ps->data==NULL)
	{
		return;//无法成功申请,就退出
	}
	ps->size=0;//设置通讯录最初有0个元素 
	ps->capacity=DEFAULT_SZ;//这里相当于初始时能存放的联系人个数 
} 

当然我这里初始化开辟的空间比较小,只能存放三个联系人,大家可以酌情增加初始大小。 

3.4通讯录的增容

有些小伙伴可能会疑惑为什么通讯录要增容,这是干什么的?其实,在我们提供的菜单中是没有这一项功能,它是实际上是我们进行添加联系人的一个前置操作——增加通讯录容量。因为我们是动态开辟的空间,所以,在添加联系人的过程中,可能会出现空间不够用的情况,这个时候继续添加联系人,就是非法占用空间了,故我们需要在添加联系人前面加上增加容量这一操作。

增容函数CheckCapacity代码如下:

void CheckCapacity(struct Contact*ps)
{
	if(ps->size == ps->capacity)
	{
		//增容
		struct PeoInfo*ptr=realloc(ps->data,(ps->capacity+2)*sizeof(struct PeoInfo));//这里申请空间时很妙地用ps->capacity+2表示个数 
		if(ptr!=NULL)
		{
			ps->data=ptr;
			ps->capacity+=2;
			printf("增容成功\n");		
		} 
		else
		{
			printf("增容失败\n");
		}
	}
}
3.5添加联系人

前面铺垫完毕,接下来就开始实现菜单中的各项功能,第一当仁不让是添加联系人。

添加联系人函数AddContact如下:

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");
}
3.6打印通讯录

打印通讯录函数ShowContact如下:

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;isize;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);
		} 
	}
}
3.7 判断联系人存在

我们在通讯录功能中有查找联系人、删除联系人、修改联系人信息等功能,但这些功能的使用前提是我们要判断该联系人是否存在,所以这里又引入一个新的铺垫性函数。

判断联系人存在函数Findbyname代码如下:

static int Findbyname(struct Contact*ps,char name[MAX_NAME])
{
	static int i=0;
	for(i=0;isize;i++)
	{
		if(0==strcmp(ps->data[i].name,name))
		{
			return i;
		}
	}
	return -1;//找不到的情况 
}
3.8删除联系人

删除联系人函数DelContact代码如下:

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;jsize-1;j++)
		{
			ps->data[j]=ps->data[j+1];
		}
		ps->size--;
		printf("删除成功\n");
	} 
}
3.9查找联系人

查找联系人函数SearchContact代码如下:

void SearchContact(const struct Contact*ps)
{
	char name[MAX_NAME];
	int pos=0;
	printf("请输入要查找人的名字:>");
	scanf("%s",&name);
	pos=Findbyname((struct Contact*)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);	
	}
}
3.10修改联系人信息

修改联系人信息函数ModifyContact代码如下:

void ModifyContact(struct Contact*ps)
{
	char name[MAX_NAME];//名字是字符串,放入数组 
	int pos=0;
	printf("请输入要修改人的名字:>");
	scanf("%s",name);
	pos=Findbyname(ps,name);
	if(pos==-1)
	{
		printf("要修改人的消息不存在\n");
	}
	else
	{
		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");
	} 
}
3.11保存联系人信息至文件

我们既然建立通讯录,肯定不想我们输入的信息不能保存,随着程序关闭就自动销毁,所以,这里我们要用到文件操作的相关知识,把我们输入的联系人信息保存到文件中,这样下次再打开文件联系人信息就还在,不会随程序关闭而销毁了。

保存联系人信息至文件函数SaveContact代码如下:

void SaveContact(Contact* ps)
{
	FILE* pf = fopen("contact.dat", "w");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return;
	}
	//写通讯录中的数据到文件中
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		fwrite(&ps->data[i], sizeof(PeoInfo), 1, pf);
	}
	fclose(pf);
	pf = NULL;
}
 3.12加载文件中联系人信息至程序

加载文件中联系人信息至程序函数LoadContact代码如下:

void LoadContact(Contact* pc)//加载通讯录
{
	FILE* fp = fopen("contact.dat", "r");
	if (fp == NULL)//判断文件是否打开
	{
		perror("LoadContact");
		return;
	}
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, fp))
	{
		if (pc->size == pc->capacity)
		{
			PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + ADD_PEO) * sizeof(PeoInfo));
			if (ptr != NULL)
			{
				pc->data = ptr;
				pc->capacity += ADD_PEO;
			}
			else
			{
				perror("AddContact");
				printf("读取通讯录失败!\n");
				return;
			}
		}
		pc->data[pc->size] = tmp;
		pc->size++;
	}
	fclose(fp);
	fp = NULL;
}
3.13销毁动态通讯录

销毁动态通讯录函数DestroyContast代码如下:

void DestroyContast(Contact*ps)
{
	free(ps->data);
	ps->data=NULL;
}
4.手机通讯录的代码实现
4.1TongXunLu.c源文件的完整代码如下:
#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); 
	LoadContact(&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:
				break;
			case EXIT:
				//销毁通讯录-释放动态开辟的内存
				printf("当前联系人信息未保存,是否继续退出?\n1.YES		2.NO\n");
			    int select = 0;
			    scanf("%d", &select);
			    if (select == 2)
			    {
			    	input = 1;
				    break;
			    }
			    else
			    {
				    DestroyContast(&con);
				    printf("退出通讯录\n");
				    break;
			    }
			case SAVE:
				SaveContact(&con);
				break;
			default:
				printf("选择错误\n");
				break;
		}
	}while(input);
	return 0;
}
4.2contact.h头文件的完整代码如下:
#define MAX 1000

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

#include
#include
#include
#include
enum Option
{
	EXIT,
	ADD,
	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个信息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(Contact* ps);

//销毁通讯录——释放动态开辟的内存 
void DestroyContact(Contact* ps);

//存储通讯录中的数据到文件 
void SaveContact(Contact *ps);

//加载文件中的信息到通讯录
void LoadContact(Contact *ps); 
4.3contact.c源文件的完整代码如下:
#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;//设置通讯录最初有0个元素 
	ps->capacity=DEFAULT_SZ;//这里相当于初始时能存放的联系人个数 
} 

void CheckCapacity(struct Contact*ps)
{
	if(ps->size == ps->capacity)
	{
		//增容
		struct PeoInfo*ptr=realloc(ps->data,(ps->capacity+2)*sizeof(struct PeoInfo));//这里申请空间时很妙地用ps->capacity+2表示个数 
		if(ptr!=NULL)
		{
			ps->data=ptr;
			ps->capacity+=2;
			printf("增容成功\n");		
		} 
		else
		{
			printf("增容失败\n");
		}
	}
}

void LoadContact(Contact* pc)//加载通讯录
{
	FILE* fp = fopen("contact.dat", "r");
	if (fp == NULL)//判断文件是否打开
	{
		perror("LoadContact");
		return;
	}
	PeoInfo tmp = { 0 };
	while (fread(&tmp, sizeof(PeoInfo), 1, fp))
	{
		if (pc->size == pc->capacity)
		{
			PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + ADD_PEO) * sizeof(PeoInfo));
			if (ptr != NULL)
			{
				pc->data = ptr;
				pc->capacity += ADD_PEO;
			}
			else
			{
				perror("AddContact");
				printf("读取通讯录失败!\n");
				return;
			}
		}
		pc->data[pc->size] = tmp;
		pc->size++;
	}
	fclose(fp);
	fp = NULL;
}

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;isize;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);
		} 
	}
}

int Findbyname(struct Contact*ps,char name[MAX_NAME])
{
	int i=0;
	for(i=0;isize;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;jsize-1;j++)
		{
			ps->data[j]=ps->data[j+1];
		}
		ps->size--;
		printf("删除成功\n");
	} 
}

void SearchContact(const struct Contact*ps)
{
	char name[MAX_NAME];
	int pos=0;
	printf("请输入要查找人的名字:>");
	scanf("%s",&name);
	pos=Findbyname((struct Contact*)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)
{
	char name[MAX_NAME];//名字是字符串,放入数组 
	int pos=0;
	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);
		ps->size++;
		printf("修改成功\n");
	} 
}

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

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

你可能感兴趣的:(有趣的代码,c语言,开发语言,青少年编程,蓝桥杯,算法,通讯录)