通讯录的实现(静态版本,动态版本,文件版本)(后附完整源代码)

这篇具有很好参考价值的文章主要介绍了通讯录的实现(静态版本,动态版本,文件版本)(后附完整源代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

一.静态版本

1.所需要的功能

对于通讯录来说,我们需要它实现以下几个功能。

1.人的信息:姓名+年龄+性别+电话+地址。
2.可以存放100个人的信息。
功能:
1>增加联系人。
2>删除联系人。
3>查找指定联系人信息。
4>修改指定联系人信息。
5>显示所有联系人信息。
6>按名字排序。

接下来分为三个模块,test.c->用来测试通讯录;contact.c->通讯录主体部分;contact.h->用于函数的声明。

2.大致菜单

#include"contact.h"


void menu()
{
	printf("********************************\n");
	printf("****** 1.增加      2.删除 ******\n");
	printf("****** 3.查找      4.修改 ******\n");
	printf("****** 5.展示      6.排序 ******\n");
	printf("*******0.退出             ******\n");
	printf("********************************\n");

}
int main()
{
	int input = 0;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			break;
		case 6:
		    break;	
		case 0:
			printf("退出通讯录。\n");
			break;
		default:
			printf("输入无效,请重新输入。\n");
			break;
		}
	} while (input);
	return 0;
}

这一块很简单,就不再多说。菜单是属于测试部分,所以我将它放入test.c文件里。

3.创建通讯录

对于一个人,肯定有多方面的因数,所以将其封装在一个结构体内。这里使用到typedef,如果不太熟悉可以看看这篇博客typedef的使用

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

接下来,再封装一个结构体里面存放100个人的信息和当前人的个数。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

接着在主函数里使用该结构体创建通讯录。然后进行初始化。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

初始化函数在contact.h里声明。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.c里实现,需要使用到memset,如果不太明白可以看看这篇博客memset如何使用

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

4.增加联系人

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.h里声明。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.c里面实现。
小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

5.显示联系人

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.h里声明。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.c里实现。这里使用到\t,向后隔开8个字节,用于分隔。同时例如%-20s是右边隔开20个字节,也就是进行左对齐。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

6.查找联系人

我们发现无论是查找,删除还是修改都需要先找到这个人。所以我们干脆将寻找封装成一个函数来使用。我们通过名字来查找(需要使用strcmp,如果不熟悉可以看看这篇博客strcmp的使用)

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

完成后正式进行查找。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

老规矩,现在contact.h里进行声明。ps:前面的find不用声明是因为find只在contact.c里使用。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.c里实现。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

7.删除联系人

这里采用一种最简单的方法,就是从后往前依次覆盖。首先找到该名字的位置,然后依次将后面的往前挪。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.h里声明。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.c里实现。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

8.修改联系人

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

老规矩在contact.h里进行声明。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.c里实现。修改其实就是重新录入,找到位置,重新写一遍就好了。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

9.按名字排序

下面排序需要使用到qsort函数。如果不太熟悉可以看看这篇博客qsort函数

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

老规矩在contact.h里声明。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.c里实现。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

好了,以上就是通讯录静态版本的实现功能啦,下面是源代码。

10.源代码

test.c

#include"contact.h"
void menu()
{
	printf("********************************\n");
	printf("****** 1.增加      2.删除 ******\n");
	printf("****** 3.查找      4.修改 ******\n");
	printf("****** 5.展示      6.排序 ******\n");
	printf("*******0.退出             ******\n");
	printf("********************************\n");

}
int main()
{
	int input = 0;
	//创建通讯录
	Contact con;//该结构体包含100个人的信息和已填充人的个数
	//初始化通讯录
	InitContact(&con);//结构体传参
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			Dlete(&con);
			break;
		case 3:
			Search(&con);
			break;
		case 4:
			Modify(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			Order(&con);
			break;
		case 0:
			printf("退出通讯录。\n");
			break;
		default:
			printf("输入无效,请重新输入。\n");
			break;
		}
	} while (input);
	return 0;
}

contact.h

#include<stdio.h>
#include<string.h>
#include<assert.h>


//人的信息
typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char addr[30];
	char tele[12];
}PeoInfo;


typedef struct Contact
{
	PeoInfo data[100];//存放人的信息
	int sz;//当前已经放的信息个数
}Contact;//同理,这里也进行了重命名


//声明初始化函数
void InitContact(Contact* pc);

//声明增加联系人函数
void AddContact(Contact*pc);

//声明显示联系人函数
void ShowContact(const Contact*pc);

//声明查找函数
void Search(const Contact*pc);//查找依然不会改变,所以加上const

//声明删除函数
void Dlete(Contact*pc);

//声明修改函数
void Modify(Contact*pc);

//声明排序函数
void Order(Contact*pc);

contact.c

#include"contact.h"



//初始化函数的实现
void InitContact(Contact* pc)
{
	pc->sz = 0;
	memset(pc->data, 0, sizeof(pc->data));
}


//增加联系人
void AddContact(Contact* pc)
{
	assert(pc);//一个好的习惯判断是否为空指针(当然不加也没影响)
	if (pc->sz == 100)
	{
		printf("通讯录已满,无法添加。\n");
		return;
	}
	//开始添加信息
	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++;//别忘了添加完一个人后向后走一步

}


//显示联系人
void ShowContact(const Contact* pc)//因为显示不会改变元素,所以最好加上const
{
	assert(pc);
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "名字", "年龄", "性别", "地址", "电话");//提示
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name,
													pc->data[i].age,
													pc->data[i].sex,
													pc->data[i].addr,
													pc->data[i].tele);
	}
}


//找到特定联系人的位置
int FindByName(const Contact* pc, char name[])//两个参数,一个是通讯录里存的名字,一个是你要查找的名字
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到返回下标
		}
	}
	return -1;//没找到,返回-1
}


//查找
void Search(const Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要查找的名字:");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("查无此人。\n");
		return;
	}
	//找到了,打印信息
	printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[pos].name,
												pc->data[pos].age,
												pc->data[pos].sex,
												pc->data[pos].addr,
												pc->data[pos].tele);
}



//删除
void Dlete(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要删除的名字:");
	scanf("%s", name);
	int dle = FindByName(pc, name);//找到位置
	if (dle == -1)
	{
		printf("查无此人。\n");
		return;
	}
	for (int i = dle; i < pc->sz-1; i++)//从后往前覆盖,同时-1避免越界
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;//删除完成后别忘了个数-1
	printf("删除成功\n");
}



//修改
void Modify(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要修改的名字:");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (-1 == ret)
	{
		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].addr);
	printf("请输入电话:");
	scanf("%s", pc->data[ret].tele);

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

//排序
int cmp(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void Order(Contact* pc)
{
	assert(pc);
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp);
	printf("排序成功\n");
}

二.动态版本

动态版本主要在静态版本的基础上加入扩容功能,如果通讯录已存满,那么会自动扩大通讯录,下面设置初始容量为三个人,如果不满足每次扩容两个人。需要的前置知识是动态内存,如果不太了解,可以看看这篇博客动态内存

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

1.修改data数组

上面的静态版本是直接开辟了一个100人的数组,很明显已经固定。所以应当将这100个人改为动态的。

静态版本
小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

动态版本

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

2.修改初始化

在静态版本的初始化里直接使用的memset指定具体的字节数来初始化。在动态版本里不知道具体的大小,很明显不能这么暴力。下面使用calloc对data进行开辟空间的同时完成初始化。

静态版本

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

动态版本

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

3.修改增加函数

在静态版本中,如果一直增加联系人到通讯录满后直接给提升:通讯录已满,不能再加入。在动态版本里需要修改,当放满通讯录后自动扩容。

静态版本

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

动态版本

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

4.完善通讯录

上面的修改大致功能没有问题了,但还有个缺陷是在开辟空间时我们在堆区上开辟的,所以在程序结束时应当主动free,避免内存泄漏。

在test.c里

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法
在contact.h里

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

在contact.c里

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

演示

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

5.源代码

test.c

#include"contact.h"
void menu()
{
	printf("********************************\n");
	printf("****** 1.增加      2.删除 ******\n");
	printf("****** 3.查找      4.修改 ******\n");
	printf("****** 5.展示      6.排序 ******\n");
	printf("*******0.退出             ******\n");
	printf("********************************\n");

}
int main()
{
	int input = 0;
	//创建通讯录
	Contact con;//该结构体包含100个人的信息和已填充人的个数
	//初始化通讯录
	InitContact(&con);//结构体传参
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			Dlete(&con);
			break;
		case 3:
			Search(&con);
			break;
		case 4:
			Modify(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			Order(&con);
			break;
		case 0:
			Destroy(&con);
			printf("退出通讯录。\n");
			break;
		default:
			printf("输入无效,请重新输入。\n");
			break;
		}
	} while (input);
	return 0;
}

contact.h

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



#define DEFAULT_SZ 3 //初始大小
#define INC_SZ 2 //每次扩容

//人的信息
typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char addr[30];
	char tele[12];
}PeoInfo;


//动态版本
typedef struct Contact
{
	PeoInfo *data;//指向存放人信息的空间
	int sz;//当前已经放的信息个数
	int capacity;//当前通讯录的最大容量
}Contact;


//声明初始化函数
void InitContact(Contact* pc);

//声明销毁函数
void Destroy(Contact* pc);

//声明增加联系人函数
void AddContact(Contact*pc);

//声明显示联系人函数
void ShowContact(const Contact*pc);

//声明查找函数
void Search(const Contact*pc);//查找依然不会改变,所以加上const

//声明删除函数
void Dlete(Contact*pc);

//声明修改函数
void Modify(Contact*pc);

//声明排序函数
void Order(Contact*pc);

contact.c

#include"contact.h"



//初始化函数的实现,动态版本
void InitContact(Contact* pc)
{
	pc->sz = 0;
	PeoInfo* ptr = (PeoInfo*)calloc(DEFAULT_SZ,sizeof(PeoInfo));//开辟初始空间
	if (ptr == NULL)
	{
		printf("%s", strerror(errno));
		return;
	}//判断是否空间开辟成功
	pc->data = ptr;
	pc->capacity = DEFAULT_SZ;//初始容量为3
}


//销毁
void Destroy(Contact* pc)
{
	free(pc->data);//由于整个data都是在堆区上开辟的,所以直接free
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
	pc = NULL;
}



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)
		{
			printf("%s", strerror(errno));
		}
		pc->data = ptr;//把新空间的起始位置传给data
		pc->capacity += INC_SZ;//最大容量加INC_SZ
		printf("增容成功\n");
	}
}
//增加联系人
void AddContact(Contact* pc)
{
	assert(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++;//别忘了添加完一个人后向后走一步

}



//显示联系人
void ShowContact(const Contact* pc)//因为显示不会改变元素,所以最好加上const
{
	assert(pc);
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "名字", "年龄", "性别", "地址", "电话");//提示
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name,
													pc->data[i].age,
													pc->data[i].sex,
													pc->data[i].addr,
													pc->data[i].tele);
	}
}


//找到特定联系人的位置
int FindByName(const Contact* pc, char name[])//两个参数,一个是通讯录里存的名字,一个是你要查找的名字
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到返回下标
		}
	}
	return -1;//没找到,返回-1
}


//查找
void Search(const Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要查找的名字:");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("查无此人。\n");
		return;
	}
	//找到了,打印信息
	printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[pos].name,
												pc->data[pos].age,
												pc->data[pos].sex,
												pc->data[pos].addr,
												pc->data[pos].tele);
}



//删除
void Dlete(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要删除的名字:");
	scanf("%s", name);
	int dle = FindByName(pc, name);//找到位置
	if (dle == -1)
	{
		printf("查无此人。\n");
		return;
	}
	for (int i = dle; i < pc->sz-1; i++)//从后往前覆盖,同时-1避免越界
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;//删除完成后别忘了个数-1
	printf("删除成功\n");
}



//修改
void Modify(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要修改的名字:");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (-1 == ret)
	{
		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].addr);
	printf("请输入电话:");
	scanf("%s", pc->data[ret].tele);

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



//排序
int cmp(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void Order(Contact* pc)
{
	assert(pc);
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp);
	printf("排序成功\n");
}

三.文件版本

我们可以发现前面两个版本在运行结束后通讯录里的信息就自动删除了,很明显是不符合我们的预期的。这是因为上面的数据都储存在内存中,而内存在一次程序运行结束后会重置,所以我们需要将其写在硬盘上(文件里),才能保证信息的存储。(需要的前置知识是文件操作,如果不太熟悉可以看看这篇博客文件操作)

1.退出前保存

test.c里
小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法
contact.h里

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法
contact.c里

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

注意文件可以建在任意位置,但如果不是在当前路径下,在fopen时记得将该文件的绝对路径写上(也就是几盘,第几文件夹…)

2.进入后读取

原来初始化通讯录时是直接初始化为0,现在初始化时将文件里的信息加载到通讯录里。

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法
小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法
小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法

3.源代码

test.c

#include"contact.h"
void menu()
{
	printf("********************************\n");
	printf("****** 1.增加      2.删除 ******\n");
	printf("****** 3.查找      4.修改 ******\n");
	printf("****** 5.展示      6.排序 ******\n");
	printf("*******0.退出             ******\n");
	printf("********************************\n");

}
int main()
{
	int input = 0;
	//创建通讯录
	Contact con;//该结构体包含100个人的信息和已填充人的个数
	//初始化通讯录
	InitContact(&con);//结构体传参
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);
			break;
		case 2:
			Dlete(&con);
			break;
		case 3:
			Search(&con);
			break;
		case 4:
			Modify(&con);
			break;
		case 5:
			ShowContact(&con);
			break;
		case 6:
			Order(&con);
			break;
		case 0:
			SaveContact(&con);
			Destroy(&con);
			printf("退出通讯录。\n");
			break;
		default:
			printf("输入无效,请重新输入。\n");
			break;
		}
	} while (input);
	return 0;
}

contact.h

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



#define DEFAULT_SZ 3 //初始大小
#define INC_SZ 2 //每次扩容

//人的信息
typedef struct PeoInfo
{
	char name[20];
	int age;
	char sex[5];
	char addr[30];
	char tele[12];
}PeoInfo;


//动态版本
typedef struct Contact
{
	PeoInfo *data;//指向存放人信息的空间
	int sz;//当前已经放的信息个数
	int capacity;//当前通讯录的最大容量
}Contact;


//声明初始化函数
void InitContact(Contact* pc);

//声明销毁函数
void Destroy(Contact* pc);

//声明增加联系人函数
void AddContact(Contact*pc);

//声明显示联系人函数
void ShowContact(const Contact*pc);

//声明查找函数
void Search(const Contact*pc);//查找依然不会改变,所以加上const

//声明删除函数
void Dlete(Contact*pc);

//声明修改函数
void Modify(Contact*pc);

//声明排序函数
void Order(Contact*pc);

//声明保存函数
void SaveContact(Contact*pc);

//声明加载通讯录函数
void LoadContact(Contact*pc);

contact.c

#include"contact.h"



//初始化函数的实现
void InitContact(Contact* pc)
{
	pc->sz = 0;
	PeoInfo* ptr = (PeoInfo*)calloc(DEFAULT_SZ,sizeof(PeoInfo));//开辟初始空间
	if (ptr == NULL)
	{
		printf("%s", strerror(errno));
		return;
	}//判断是否空间开辟成功
	pc->data = ptr;
	pc->capacity = DEFAULT_SZ;//初始容量为3

	//加载数据到通讯录
	LoadContact(pc);
}


//销毁
void Destroy(Contact* pc)
{
	free(pc->data);//由于整个data都是在堆区上开辟的,所以直接free
	pc->data = NULL;
	pc->capacity = 0;
	pc->sz = 0;
	pc = NULL;
}



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)
		{
			printf("%s", strerror(errno));
		}
		pc->data = ptr;//把新空间的起始位置传给data
		pc->capacity += INC_SZ;//最大容量加INC_SZ
		printf("增容成功\n");
	}
}
//增加联系人
void AddContact(Contact* pc)
{
	assert(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++;//别忘了添加完一个人后向后走一步

}



//显示联系人
void ShowContact(const Contact* pc)//因为显示不会改变元素,所以最好加上const
{
	assert(pc);
	printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "名字", "年龄", "性别", "地址", "电话");//提示
	for (int i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name,
													pc->data[i].age,
													pc->data[i].sex,
													pc->data[i].addr,
													pc->data[i].tele);
	}
}


//找到特定联系人的位置
int FindByName(const Contact* pc, char name[])//两个参数,一个是通讯录里存的名字,一个是你要查找的名字
{
	for (int i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name) == 0)
		{
			return i;//找到返回下标
		}
	}
	return -1;//没找到,返回-1
}


//查找
void Search(const Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要查找的名字:");
	scanf("%s", name);
	int pos = FindByName(pc, name);
	if (pos == -1)
	{
		printf("查无此人。\n");
		return;
	}
	//找到了,打印信息
	printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[pos].name,
												pc->data[pos].age,
												pc->data[pos].sex,
												pc->data[pos].addr,
												pc->data[pos].tele);
}



//删除
void Dlete(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要删除的名字:");
	scanf("%s", name);
	int dle = FindByName(pc, name);//找到位置
	if (dle == -1)
	{
		printf("查无此人。\n");
		return;
	}
	for (int i = dle; i < pc->sz-1; i++)//从后往前覆盖,同时-1避免越界
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;//删除完成后别忘了个数-1
	printf("删除成功\n");
}



//修改
void Modify(Contact* pc)
{
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要修改的名字:");
	scanf("%s", name);
	int ret = FindByName(pc, name);
	if (-1 == ret)
	{
		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].addr);
	printf("请输入电话:");
	scanf("%s", pc->data[ret].tele);

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



//排序
int cmp(const void* e1, const void* e2)
{
	return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
void Order(Contact* pc)
{
	assert(pc);
	qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp);
	printf("排序成功\n");
}



//保存
void SaveContact(Contact* pc)
{
	//第一步打开文件
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("fopen:");
	}
	else
	{
		//写数据,一个人一个人的写
		//data数组里一个元素就是一个结构体,也就是一个人
		for (int i = 0; i < pc->sz; i++)
		{
			fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
		}
		fclose(pf);
		pf = NULL;
		printf("保存成功\n");
	}
}


//加载通讯录
void LoadContact(Contact* pc)
{
	//打开文件
	FILE*pf=fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("LoadCContact:");
	}
	else
	{
		//读取文件
		PeoInfo tmp = { 0 };
		int i = 0;
		while (fread(&tmp, sizeof(PeoInfo), 1, pf))//一次读一个人,如果读取完毕返回0
		{
			//写数据
			//由于在退出时销毁了通讯录,所以回到初始大小,如果存储的数据打于初始容量,需要扩容
			check_capacity(pc);//检查是否需要扩容,如果需要就扩容
			
			pc->data[i] = tmp;
			pc->sz++;
			i++;
		}
		fclose(pf);
		pf = NULL;
	}
}

小型通讯录源代码实现,# 经典小游戏,c++,c语言,算法文章来源地址https://www.toymoban.com/news/detail-803232.html

到了这里,关于通讯录的实现(静态版本,动态版本,文件版本)(后附完整源代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • C语言---认识动态内存管理并实现一个动态通讯录:静态通讯录别来沾边

    C语言---认识动态内存管理并实现一个动态通讯录:静态通讯录别来沾边

    👧个人主页:@小沈熬夜秃头中୧⍤⃝❅ 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 📋专栏:C语言学习 🔑本章内容:动态内存管理 送给各位💌:当你的能力还驾驭不了你的目标时那你就应该沉下心来历练 记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~ 提示:以下是本篇

    2024年02月08日
    浏览(67)
  • 手机通讯录的实现——C语言(静态版本)

    手机通讯录的实现——C语言(静态版本)

    目录 一:通讯录的思想 二:通讯录的实现 1.创建文件 2.打印菜单 3.创建联系人结构体 4.初始化菜单 5.实现菜单的功能 a.增加联系人 b.删除联系人 c.查找联系人 d.修改联系人 e.打印联系人 三:总结 我们将每一位联系人的姓名,性别,年龄,电话,地址来用一个结构体保存,用

    2024年02月09日
    浏览(9)
  • C语言动态内存练习:【通讯录(动态内存版本)实现】

    前面我们写了一个静态数组版本的通讯录,再结合刚学习的动态内存管理的知识,我们现在来实现一个动态内存版本的通讯录。 动态内存版本的通讯录,主要还是为了解决静态数组版本的通讯录空间太大导致的内存浪费和空间太小不够存放的问题。 扩容策略: 为通讯录设置

    2023年04月13日
    浏览(15)
  • 【C语言】实现通讯录(动态+文件)

    【C语言】实现通讯录(动态+文件)

    在之前三子棋和扫雷的基础上,本篇文章博主将给大家逐步分析实现通讯录,介绍通讯录的每个功能( 动态增长和文件保存 )。 —————————————————————— test.c - 测试通讯录 Contact.c - 函数的实现 Contact.h - 函数和类型的声明 以多文件的形式分模块写的

    2024年02月13日
    浏览(31)
  • 动态内存管理函数介绍及C语言实现通讯录管理系统2.0版(动态增长版本)

    动态内存管理函数介绍及C语言实现通讯录管理系统2.0版(动态增长版本)

    之前向大家介绍了C语言实现通讯录管理系统1.0版本,但该版本有明显的不足之处,比如:一开始就开辟了1000个date数组,如果联系人很少,那么就会造成严重的内存浪费,或者联系人超过了1000人,那么原数组就放不下了,所以今天我们考虑使用动态内存管理的办法来实现一个

    2023年04月08日
    浏览(8)
  • 文件操作介绍及C语言实现通讯录管理系统3.0最终版(文件操作版本)

    文件操作介绍及C语言实现通讯录管理系统3.0最终版(文件操作版本)

    上一篇文章我们学习了动态内存开辟的相关知识点,并用动态内存函数优化了我们的通讯录,但通讯录还有需要改进的地方,比如,正常情况下的通讯录,应该可以一直保存联系人信息,而不是退出就清空了,这就需要我们实实在在的保存下来一个通讯录。 接下来我会给大家

    2023年04月08日
    浏览(11)
  • 【创作赢红包】循序渐进的全版本通讯录详解,可保存信息的动态通讯录

    【创作赢红包】循序渐进的全版本通讯录详解,可保存信息的动态通讯录

    之前的博客里我们实现了 静态 的通讯录。|ू・ω・` ) 静态通讯录,适合初学者的手把手一条龙讲解_陈大大陈的博客-CSDN博客 这个版本的通讯录 无法实现容量的动态增加,也无法保存我们输入的信息。(•́へ•́╬) 静态通讯录,是直接开辟100块空间内存来供使用,但是这样

    2023年04月17日
    浏览(62)
  • 通讯录的实现(静态入手版)

    通讯录的实现(静态入手版)

    🍉博客主页:阿博历练记 📖文章专栏:c语言(初阶与进阶) 🎁代码仓库:阿博编程日记 🌹欢迎关注:欢迎友友们点赞收藏+关注哦 在生活中,我们可以通过通讯录快速实现对一位好友的查找,便捷了我们的日常生活,今天阿博就带领友友们一起探索通讯录的实现🙈🙈🙈

    2024年02月02日
    浏览(14)
  • C语言——静态通讯录的实现

    C语言——静态通讯录的实现

    今天我们来实现一下一个静态的通讯录: 我就先展示一下几个功能: 实现一个通讯录; 通讯录可以用来存储100个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址 提供方法: 添加联系人信息 删除指定联系人信息 查找指定联系人信息 修改指定联系人信息 显示

    2024年01月22日
    浏览(36)
  • C语言实现通讯录--静态版

    C语言实现通讯录--静态版

    实现一个通讯录 ,里面存放100个人的信息,完成通讯录的基本操作功能:增删查改联系人 (1)通讯录存放100个人的信息? 创建一个数组作为通讯录,100个元素,每个元素里面存放每个人的信息,所以数组里面的每个元素应该是结构体类型。 (2)每个人的信息应该包括哪些

    2024年02月16日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包