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

❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️

❇️❇️❇️❇️ 不同的信念 ❇️❇️❇️❇️

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

❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️❇️

📖通讯录

✅具备的功能

ℹ️需要的头文件名

c 复制代码
#include<stdio.h>//第一个
#include<string.h>//第二个
#include<stdlib.h>//第三个

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

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

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

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

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

c 复制代码
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");
}
c 复制代码
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;
}

ℹ️添加联系人

c 复制代码
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()函数就是来添加联系人

ℹ️删除联系人

c 复制代码
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");
		}
	}
}

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

ℹ️显示联系人

c 复制代码
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);
	}
}

ℹ️查找联系人

c 复制代码
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就是用来比较字符串大小的函数,它的用法在我以前写的博客中有介绍大家可以去看看:字符和字符串的库函数模拟(这是一个链接有需要的可以直接点进去看)

ℹ️修改联系人

c 复制代码
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");
		}
	}
}

ℹ️联系人排序

c 复制代码
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函数搭配使用。参考相关资料。(抱歉)

ℹ️清空联系人

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

ℹ️退出通讯录

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

ℹ️通讯录置空

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

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

ℹ️普通的通讯录实现

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

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

✅动态文件操作实现过程

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

c 复制代码
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语言)(这是一个链接,大家对于文件方面知识的欠缺可以点进去看)。

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

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语言)(这是一个链接,大家对于文件方面知识的欠缺可以点进去看)。

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

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

✏️✏️✏️✏️📖📖✏️✏️✏️✏️✏️✏️✏️📖📖✏️✏️

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

✏️✏️✏️✏️📖📖✏️✏️✏️✏️✏️✏️📖📖✏️✏️

相关推荐
远望清一色15 分钟前
基于MATLAB的实现垃圾分类Matlab源码
开发语言·matlab
confiself24 分钟前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
XiaoLeisj36 分钟前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee
杜杜的man39 分钟前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*40 分钟前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
半桶水专家41 分钟前
go语言中package详解
开发语言·golang·xcode
llllinuuu42 分钟前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s42 分钟前
Golang--协程和管道
开发语言·后端·golang
王大锤439144 分钟前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
为什么这亚子1 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算