通讯录(C语言文件版本)(超详细过程)

请添加图片描述

❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️
❇️❇️❇️❇️ 不同的信念 ❇️❇️❇️❇️
❇️❇️❇️ 决定不同的命运 ❇️❇️❇️
❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️

📖通讯录

✅具备的功能

ℹ️需要的头文件名

#include<stdio.h>//第一个
#include<string.h>//第二个
#include<stdlib.h>//第三个

第一个头文件名是常规的头文件名如:int main()主函数和printf函数等都需要,只要写C语言都需要此头文件名。

第二个头文件名是在下面执行通讯录文件时需要使用strcmp函数会用到

第三个头文件名也是在下面执行通讯录文件时会用到,如:qsort()函数和free()函数会用到

当然这些函数的用途,在讲解通讯录的时候会个哦大家介绍。

ℹ️所用到的其它函数和相关结构体

typedef struct Proper//所存储的人的信息
{
	char name[20];//姓名
	int age;//年龄
	char number[20];//电话号码
}Proper;

typedef struct Contact存储人信息的空间
{
	Proper* date;//存储人信息的指针
	int se;//空间里存储联系人信息的数量
	int eff;//空间总的大小
}Contact;

void Inialize(Contact* con)//存储联系人信息的数组初始化
{
	con->date = (Proper*)malloc(3 * sizeof(Proper));
	if (con->date == NULL)
	{
		perror("Inialize");
		return;
	}
	con->se = 0;
	con->eff = 3;
}

void menu()//游戏菜单
{
	printf("*******************************\n");
	printf("***** 1、添加联系人 ***********\n");
	printf("***** 2、删除联系人 ***********\n");
	printf("***** 3、显示联系人 ***********\n");
	printf("***** 4、查找联系人 ***********\n");
	printf("***** 5、修改联系人 ***********\n");
	printf("***** 6、联系人排序 ***********\n");
	printf("***** 7、清空联系人 ***********\n");
	printf("***** 8、退出通讯录 ***********\n");
	printf("*******************************\n");
}
void test()//通讯录函数
{
	int input = 0;
	Contact con;
	Inialize(&con);//通讯录初始化
	do
	{
		menu();//游戏菜单
		printf("请作出选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);//添加联系人
			break;
		case 2:
			Delete(&con);//删除联系人
			break;
		case 3:
			Display(&con);//显示联系人
			break;
		case 4:
			SeekContact(&con);//查找联系人
			break;
		case 5:
			Modify(&con);//修改联系人
			break;
		case 6:
			SortContact(&con);//联系人排序
			break;
		case 7:
			empty(&con);
			break;
		case 8:
			SaveContact(&con);
			realse(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("输入有误,请重新输入\n");
			break;
		}
		if (input == 8)
			input = 0;
	} while (input);
}
int main()//主函数
{
	test();
	return 0;
}

ℹ️添加联系人

int  Addeff(Contact* con)//检查存储空间是否满的函数
{
	if (con->se == con->eff)//两者相等时会满,除了首次进入两个都为0的情况
	{
		Proper* per = (Proper*)realloc(con->date, (con->eff + 2) * sizeof(Proper));
		if (per == NULL)//判断per空间的创建是否成功
		{
			perror("Addeff");
			return 0;
		}
		con->date = per;
		con->eff = con->eff + 2;
		printf("增容成功\n");
	}
	return 1;
}
void AddContact(Contact* con)//添加联系人函数
{
	if (Addeff(con) == 0)//如果Addeff函数如果返回0,则表示空间创建失败,则不可以添加联系人
	{
		return;
	}

	printf("输入姓名:>");
	scanf("%s", con->date[con->se].name);

	printf("输入年龄:>");
	scanf("%d", &con->date[con->se].age);//这里会什么会加&(地址符)呢,这是因为输入的是一个数,而上面输入不需要加&,是因为是数组。数组首元素就是该数组的大小
	
	printf("输入电话号码:>");
	
	scanf("%s", con->date[con->se].number);
	
	con->se++;
	printf("添加成功\n");
}

Addeff函数是用来检查我们所用来存储联系人的空间有没有满,如果满了,就会利用此函数来增加空间。Contact()函数就是来添加联系人

ℹ️删除联系人

void Delete(Contact* con)//删除联系人函数
{
	int i = 0;
	char m[20] = { 0 };//创建一个新的数组用来输入你需要查找的联系人的空间
	printf("输入你需要删除联系人的姓名:>");
	scanf("%s", m);
	for (i = 0; i < con->se; i++)//在数据里查找你需要删除的联系人的信息
	{
		int j = 0;
		if (strcmp(m, con->date[i].name) == 0)
		{
			for (j = i; j < con->se - 1; j++)//当你找到你所要删除的联系人的消息的时候,利用后面的数据把此数据进行覆盖,这样就达到删除的功效
			{

				con->date[j] = con->date[j + 1];
			}
			con->se--;//当你删除联系人的时候该联系人后面的数据都往前移了一步,这样最后就多了一个空间,此时我们就需要删掉这个空间
			printf("删除成功\n");
		}
	}
}

此过程还是很好理解的,因为存储联系人的信息是数组,所以我们只能利用覆盖来删除。

ℹ️显示联系人

void  Display(Contact* con)//打印通讯录所有联系人信息的函数
{
	int i = 0;
	printf("%-10s  %-10s  %-10s\n", "姓名", "年龄", "电话");
	for (i = 0; i < con->se; i++)
	{
		printf("%-10s  %-10d  %-10s\n", con->date[i].name, con->date[i].age, con->date[i].number);
	}
}

ℹ️查找联系人

void SeekContact(Contact* con)
{
	int i = 0;
	char m[20] = { 0 };//和删除联系人所需创建的变量是同一个意思,在这里它就是存储你需要查找的联系人的信息
	printf("输入你要查找的联系人的姓名:>");
	scanf("%s", m);
	for (i = 0; i < con->se; i++)//遍历一遍
	{
		if (strcmp(m, con->date[i].name) == 0)//利用了strcmp函数
		{
			printf("找到了:姓名:%s, 年龄:%d, 号码:%s\n", con->date[i].name, con->date[i].age, con->date[i].number);
		}
	}
}

strcmp就是用来比较字符串大小的函数,它的用法在我以前写的博客中有介绍大家可以去看看:字符和字符串的库函数模拟(这是一个链接有需要的可以直接点进去看)

ℹ️修改联系人

void Modify(Contact* con)//修改联系人信息的函数
{
	char m[20] = { 0 };//这里与上面的用法差不多,用来存储你需要查找联系人的信息
	printf("输入你需要修改联系人的姓名:>");
	scanf("%s", m);
	int i = 0;
	for (i = 0; i < con->se; i++)//遍历一遍
	{
		if (strcmp(m, con->date[i].name) == 0)//利用了strcmp函数
		{
			printf("重新输入姓名:>");
			scanf("%s", con->date[i].name);

			printf("重新输入年龄:>");
			scanf("%d", &con->date[i].age);//这里会什么会加&(地址符)呢,这是因为输入的是一个数,而上面输入不需要加&,是因为是数组。数组首元素就是该数组的大小

			printf("重新输入号码:>");
			scanf("%s", con->date[i].number);

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

ℹ️联系人排序

int compare(const void* p1, const void* p2)//比较函数
{
	return strcmp(((Proper*)p1)->name, ((Proper*)p2)->name);
}

void  SortContact(Contact* con)//用来进行联系人排序的函数
{
	qsort(con->date, con->se, sizeof(Proper), compare);//这是一个专门进行排序的函数
	printf("成功排序\n");
}

qsort()函数:可以参考相关的博客,也可以百度,在这里就不做过多解释了(抱歉)
compare()函数:此函数是和qsort函数搭配使用。参考相关资料。(抱歉)

ℹ️清空联系人

void empty(Contact* con)//清除联系人的函数
{
	con->se = 0;//因为con->se表示的是数组空间类的大小,当空间为0的时候这组也就没有数据了
	printf("成功清除\n");
}

ℹ️退出通讯录

当input输入为0的时候程序就退出了

ℹ️通讯录置空

void realse(Contact* con)//通讯录空间置空的函数
{
	free(con->date);//置空函数,只要是动态开辟的空间都需要使用该函数进行置空,否者就会有内存泄漏的情况
	con->date = NULL;//和free是搭配使用的
	con->se = 0;
	con->eff = 0;
}

关于free()函数的用法。大家可以看我以前这篇的博客:动态内存管理(c语言)(这是个链接,有不清楚的可以点进去观看,里面对于懂得太内存有详细的介绍)

ℹ️普通的通讯录实现

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct Proper
{
	char name[20];
	int age;
	char number[20];
}Proper;

typedef struct Contact
{
	Proper* date;
	int se;
	int eff;
}Contact;

void menu()
{
	printf("*******************************\n");
	printf("***** 1、添加联系人 ***********\n");
	printf("***** 2、删除联系人 ***********\n");
	printf("***** 3、显示联系人 ***********\n");
	printf("***** 4、查找联系人 ***********\n");
	printf("***** 5、修改联系人 ***********\n");
	printf("***** 6、联系人排序 ***********\n");
	printf("***** 7、清空联系人 ***********\n");
	printf("***** 8、退出通讯录 ***********\n");
	printf("*******************************\n");
}

void Inialize(Contact* con)
{
	con->date = (Proper*)malloc(3 * sizeof(Proper));
	if (con->date == NULL)
	{
		perror("Inialize");
		return;
	}
	con->se = 0;
	con->eff = 3;
}

int  Addeff(Contact* con)
{
	if (con->se == con->eff)
	{
		Proper* per = (Proper*)realloc(con->date, (con->eff + 2) * sizeof(Proper));
		if (per == NULL)
		{
			perror("Addeff");
			return 0;
		}
		con->date = per;
		con->eff = con->eff + 2;
		printf("增容成功\n");
	}
	return 1;
}

void AddContact(Contact* con)
{
	if (Addeff(con) == 0)
	{
		return;
	}

	printf("输入姓名:>");
	scanf("%s", con->date[con->se].name);

	printf("输入年龄:>");
	scanf("%d", &con->date[con->se].age);

	printf("输入电话号码:>");
	scanf("%s", con->date[con->se].number);

	con->se++;

	printf("添加成功\n");

}

void  Display(Contact* con)
{
	int i = 0;
	printf("%-10s  %-10s  %-10s\n", "姓名", "年龄", "电话");
	for (i = 0; i < con->se; i++)
	{
		printf("%-10s  %-10d  %-10s\n", con->date[i].name, con->date[i].age, con->date[i].number);
	}
}

void Delete(Contact* con)
{
	int i = 0;
	char m[20] = { 0 };
	printf("输入你需要删除联系人的姓名:>");
	scanf("%s", m);
	for (i = 0; i < con->se; i++)
	{
		int j = 0;
		if (strcmp(m, con->date[i].name) == 0)
		{
			for (j = i; j < con->se - 1; j++)
			{

				con->date[j] = con->date[j + 1];
			}
			con->se--;
			printf("删除成功\n");
		}
	}
}

void SeekContact(Contact* con)
{
	int i = 0;
	char m[20] = { 0 };
	printf("输入你要查找的联系人的姓名:>");
	scanf("%s", m);
	for (i = 0; i < con->se; i++)
	{
		if (strcmp(m, con->date[i].name) == 0)
		{
			printf("找到了:姓名:%s, 年龄:%d, 号码:%s\n", con->date[i].name, con->date[i].age, con->date[i].number);
		}
	}
}

void Modify(Contact* con)
{
	char m[20] = { 0 };
	printf("输入你需要修改联系人的姓名:>");
	scanf("%s", m);
	int i = 0;
	for (i = 0; i < con->se; i++)
	{
		if (strcmp(m, con->date[i].name) == 0)
		{
			printf("重新输入姓名:>");
			scanf("%s", con->date[i].name);

			printf("重新输入年龄:>");
			scanf("%d", &con->date[i].age);

			printf("重新输入号码:>");
			scanf("%s", con->date[i].number);

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

int compare(const void* p1, const void* p2)
{
	return strcmp(((Proper*)p1)->name, ((Proper*)p2)->name);
}

void  SortContact(Contact* con)
{
	qsort(con->date, con->se, sizeof(Proper), compare);
	printf("成功排序\n");
}

void empty(Contact* con)
{
	con->se = 0;
	printf("成功清除\n");
}

void realse(Contact* con)
{
	free(con->date);
	con->date = NULL;
	con->se = 0;
	con->eff = 0;
}

void test()
{
	int input = 0;
	Contact con;
	Inialize(&con);//通讯录初始化
	do
	{
		menu();//游戏菜单
		printf("请作出选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);//添加联系人
			break;
		case 2:
			Delete(&con);//删除联系人
			break;
		case 3:
			Display(&con);//显示联系人
			break;
		case 4:
			SeekContact(&con);//查找联系人
			break;
		case 5:
			Modify(&con);//修改联系人
			break;
		case 6:
			SortContact(&con);//联系人排序
			break;
		case 7:
			empty(&con);
			break;
		case 8:
			realse(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("输入有误,请重新输入\n");
			break;
		}
		if (input == 8)
			input = 0;
	} while (input);
}

int main()
{
	test();
	return 0;
}

上面就是普通的通讯录的实现代码了。有需要的直接复制粘贴就可以了。

✅动态文件操作实现过程

ℹ️联系人信息保存在文件中

void SaveContact(Contact* con)
{
	FILE* fp = fopen("C:\\Users\\杨沛琪\\Desktop\\contact.txt", "wb");//这就是文件的创建
	if (fp == NULL)//这是文件的判断,如果创建的文件为空,则直接结束该函数,不会进行下一步
	{
		perror("fopen");
		return;
	}
	for (int i = 0; i < con->se; i++)
	{
		fwrite(&(con->date[i]), sizeof(Proper), 1, fp);//这是把数组的数据存储到我们刚才创建的文件fp中
	}
	fclose(fp);//文件置空,和free用法一样只不过fclose是文件置空使用,free是动态空间使用
	fp = NULL;//和fclose两者是搭配使用的

}

大家如果对于文件方面的操作不太了解的话,如:FILE,fwrite,fread等的用法,大家可以观看我的这篇博客文件详细操作过程(C语言)(这是一个链接,大家对于文件方面知识的欠缺可以点进去看)。

ℹ️从文件中读取联系人的信息

void LoadContact(Contact* con)//读取文件中联系人的信息
{
	FILE* fp = fopen("C:\\Users\\杨沛琪\\Desktop\\contact.txt", "rb");
	if (fp == NULL)
	{
		perror("LoadContact");
		return;
	}
	Proper tem = { 0 };
	while (fread( & tem, sizeof(Proper), 1, fp))//fread()函数是读取文件的函数
	{		
		if (0 == Addeff(con))
			return;
		con->date[con->se] = tem;
		con->se++;
	}
	//为什么要把函数放在while循环中呢?这是因为fread的返回值是整数型。它读取一个数据就会返回1,读取两个就返回2,以此类推,当读取的数据为空时就会返回0.
	fclose(fp);//置空函数,和free用法一样,只不过fclose是文件置空而free是动态空间置空
	fp = NULL;//和fclose搭配使用
}
void Inialize(Contact* con)//存储联系人信息的数组初始化
{
	con->date = (Proper*)malloc(3 * sizeof(Proper));
	if (con->date == NULL)
	{
		perror("Inialize");
		return;
	}
	con->se = 0;
	con->eff = 3;
	LoadContact(con);//和普通的通讯录实现中的初始化仅仅多了这一个函数,当我们需要在程序执行前读取文件中所存储的联系人信息,只能放在初始化过程中实现。
}

大家如果对于文件方面的操作不太了解的话,如:FILE,fwrite,fread等的用法,大家可以观看我的这篇博客文件详细操作过程(C语言)(这是一个链接,大家对于文件方面知识的欠缺可以点进去看)。

ℹ️通讯录(文件形式)实现过程

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

typedef struct Proper
{
	char name[20];
	int age;
	char number[20];
}Proper;

typedef struct Contact
{
	Proper* date;
	int se;
	int eff;
}Contact;

void menu()
{
	printf("*******************************\n");
	printf("***** 1、添加联系人 ***********\n");
	printf("***** 2、删除联系人 ***********\n");
	printf("***** 3、显示联系人 ***********\n");
	printf("***** 4、查找联系人 ***********\n");
	printf("***** 5、修改联系人 ***********\n");
	printf("***** 6、联系人排序 ***********\n");
	printf("***** 7、清空联系人 ***********\n");
	printf("***** 8、退出通讯录 ***********\n");
	printf("*******************************\n");
}

int  Addeff(Contact* con);//因为Addeff函数在创建的时候是在下面,而在它之前的函数需要调用的时候就会找不到,所以就需要提前写一个声明。在C语言中函数执行顺序是从上往下。

void LoadContact(Contact* con)
{
	FILE* fp = fopen("C:\\Users\\杨沛琪\\Desktop\\contact.txt", "rb");
	if (fp == NULL)
	{
		perror("LoadContact");
		return;
	}
	Proper tem = { 0 };
	while (fread( & tem, sizeof(Proper), 1, fp))
	{
		if (0 == Addeff(con))
			return;
		con->date[con->se] = tem;
		con->se++;
	}
	fclose(fp);
	fp = NULL;
}

void Inialize(Contact* con)
{
	con->date = (Proper*)malloc(3 * sizeof(Proper));
	if (con->date == NULL)
	{
		perror("Inialize");
		return;
	}
	con->se = 0;
	con->eff = 3;
	LoadContact(con);
}

int  Addeff(Contact* con)
{
	if (con->se == con->eff)
	{
		Proper* per = (Proper*)realloc(con->date, (con->eff + 2) * sizeof(Proper));
		if (per == NULL)
		{
			perror("Addeff");
			return 0;
		}
		con->date = per;
		con->eff = con->eff + 2;
		printf("增容成功\n");
	}
	return 1;
}

void AddContact(Contact* con)
{
	if (Addeff(con) == 0)
	{
		return;
	}

	printf("输入姓名:>");
	scanf("%s", con->date[con->se].name);

	printf("输入年龄:>");
	scanf("%d", &con->date[con->se].age);

	printf("输入电话号码:>");
	scanf("%s", con->date[con->se].number);

	con->se++;

	printf("添加成功\n");

}

void  Display(Contact* con)
{
	int i = 0;
	printf("%-10s  %-10s  %-10s\n", "姓名", "年龄", "电话");
	for (i = 0; i < con->se; i++)
	{
		printf("%-10s  %-10d  %-10s\n", con->date[i].name, con->date[i].age, con->date[i].number);
	}
}

void Delete(Contact* con)
{
	int i = 0;
	char m[20] = { 0 };
	printf("输入你需要删除联系人的姓名:>");
	scanf("%s", m);
	for (i = 0; i < con->se; i++)
	{
		int j = 0;
		if (strcmp(m, con->date[i].name) == 0)
		{
			for (j = i; j < con->se - 1; j++)
			{

				con->date[j] = con->date[j + 1];
			}
			con->se--;
			printf("删除成功\n");
		}
	}
}

void SeekContact(Contact* con)
{
	int i = 0;
	char m[20] = { 0 };
	printf("输入你要查找的联系人的姓名:>");
	scanf("%s", m);
	for (i = 0; i < con->se; i++)
	{
		if (strcmp(m, con->date[i].name) == 0)
		{
			printf("找到了:姓名:%s, 年龄:%d, 号码:%s\n", con->date[i].name, con->date[i].age, con->date[i].number);
		}
	}
}

void Modify(Contact* con)
{
	char m[20] = { 0 };
	printf("输入你需要修改联系人的姓名:>");
	scanf("%s", m);
	int i = 0;
	for (i = 0; i < con->se; i++)
	{
		if (strcmp(m, con->date[i].name) == 0)
		{
			printf("重新输入姓名:>");
			scanf("%s", con->date[i].name);

			printf("重新输入年龄:>");
			scanf("%d", &con->date[i].age);

			printf("重新输入号码:>");
			scanf("%s", con->date[i].number);

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

int compare(const void* p1, const void* p2)
{
	return strcmp(((Proper*)p1)->name, ((Proper*)p2)->name);
}

void  SortContact(Contact* con)
{
	qsort(con->date, con->se, sizeof(Proper), compare);
	printf("成功排序\n");
}

void empty(Contact* con)
{
	con->se = 0;
	printf("成功清除\n");
}

void realse(Contact* con)
{
	free(con->date);
	con->date = NULL;
	con->se = 0;
	con->eff = 0;
}

void SaveContact(Contact* con)
{
	assert(con);
	FILE* fp = fopen("C:\\Users\\杨沛琪\\Desktop\\contact.txt", "wb");
	if (fp == NULL)
	{
		perror("fopen");
		return;
	}
	for (int i = 0; i < con->se; i++)
	{
		fwrite(&(con->date[i]), sizeof(Proper), 1, fp);
	}
	fclose(fp);
	fp = NULL;

}

void test()
{
	int input = 0;
	Contact con;
	Inialize(&con);//通讯录初始化
	do
	{
		menu();//游戏菜单
		printf("请作出选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			AddContact(&con);//添加联系人
			break;
		case 2:
			Delete(&con);//删除联系人
			break;
		case 3:
			Display(&con);//显示联系人
			break;
		case 4:
			SeekContact(&con);//查找联系人
			break;
		case 5:
			Modify(&con);//修改联系人
			break;
		case 6:
			SortContact(&con);//联系人排序
			break;
		case 7:
			empty(&con);
			break;
		case 8:
			SaveContact(&con);
			realse(&con);
			printf("退出通讯录\n");
			break;
		default:
			printf("输入有误,请重新输入\n");
			break;
		}
		if (input == 8)
			input = 0;
	} while (input);
}

int main()
{
	test();
	return 0;
}

在这里插入图片描述

✏️✏️✏️✏️📖📖✏️✏️✏️✏️✏️✏️✏️📖📖✏️✏️
✏️✏️✏️✏️📖📖我们一起加油哈!!📖📖✏️✏️
✏️✏️✏️✏️📖📖✏️✏️✏️✏️✏️✏️📖📖✏️✏️

  • 97
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 58
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 58
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悦心无谓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值