300行C代码完成动态通讯录管理

Posted Aline2021-yxz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了300行C代码完成动态通讯录管理相关的知识,希望对你有一定的参考价值。

明确通讯录功能

本次带大家完成的是比较简单的通讯录,所以实现的功能也是比较简单,功能如下:
1:向通讯录中添加成员
2:删除成员
3:修改成员
4:显示全部成员
5:按名字排序所有成员
6:查找成员并显示
7:退出

核心思想

动态通讯录管理的意思就是通讯录的大小是可以变化的,所以需要动态申请堆空间,我们就是对申请的连续的堆空间进行操作。

对象创建和初始化

在实现功能之前我们需要写的代码:
1:创建人这个对象

typedef struct people
{
	char name[10];//姓名
	char sex;//性别
	char address[25];//居住地址
	int age;//年龄
	char number[12];//电话
}people;

2:创建通讯录
通讯录应该包括什么呢?
1:要包括人这个对象,我们本来可以使用数组实现,但现在要动态管理,所以使用指向人这个对象的指针代替。
2:要判断通讯录满没满,所以必须知道通讯录的人员数量
3:我们需要知道通讯录的最大值吧,不然人员数量和谁比较呢?

typedef struct Contact
{
	people* can;//存放通讯录人员的容器指针
	int count;//通讯录的人员数量
	int max;//通讯录最大容量
}Contact;

3:通讯录初始化:

extern void InitContact(Contact* Contactlist)
{
	Contactlist->can = (people*)malloc(sizeof(*(Contactlist->can))*10);//动态内存申请
	Contactlist->count = 0;
	Contactlist->max = 10;
}

光申请可不行,还要判断是否申请成功

	if (Contactlist.can == NULL)
	{
		perror("room");//打印错误原因
		return 0;
	}

功能实现

1:添加人员
需要注意我们在添加人员之前务必要判断动态申请的空间是否已经满了。

void peopleAdd(Contact* p)
{
	char name1[10];
	char sex1;
	char address1[25];
	int age1;
	char number1[12];	
	if (p->count == p->max)//通讯录已满,需要调整通讯录大小
	{
		people *tmp = realloc(p->can, (p->max) * 2);//调整为原来的二倍
		if (tmp == NULL)//判断申请时候成功
		{
			perror("room");
			return;
		}
		else//使原指针指向新空间
		{
			p->can = tmp;
			(p->max) *= 2;//通讯录长度自然加长为原来二倍
		}
	}

	printf("请输入姓名:");
	scanf("%s", name1);
	printf("请输入性别:");
	scanf(" %c", &sex1);
	printf("请输入年龄:");
	scanf("%d", &age1);
	printf("请输入电话:");
	scanf("%s", number1);
	printf("请输入地址:");
	scanf("%s", address1);
//对人员赋值:
	strcpy((p->can + (p->count))->name, name1);
	(p->can + (p->count))->sex = sex1;
	(p->can + (p->count))->age = age1;
	strcpy((p->can + (p->count))->number, number1);
	strcpy((p->can + (p->count))->address, address1);
	(p->count)++;

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

2:删除成员

void peopleDel(Contact*p)
{
	int a = 0;
	char input = 0;
	char name2[10] = { 0 };
	if (p->count == 0)
	{
		printf("当前通讯录无成员\\n");
		return ;
	}
	printf("请输入要删除人员的姓名:");
	scanf("%s", name2);
	for (a = 0; a < p->count; a++)//通过循环来寻找是否存在人员
	{
		if (strcmp(name2, (p->can + a)->name)==0)//找到了
		{
			printf("是否要删除此成员?(y/n)\\n");
			scanf(" %c", &input);//空格是防止将换行符直接赋值
			if (input == 'y')
			{
				for (int b = a; b < p->count - 2; b++)//通过将后面的元素全部向前挪一个单位来删除对应人员
				{
					*(p->can + b) = *(p->can + b + 1);
				}
				printf("删除成功!\\n");
				p->count--;
				return;
			}
			else 
				return;
		}
		if (a == p->count-1)//全部找完了还没找到的情况
		{
			printf("查无此人!\\n");
		}
	}
}

修改人员与查找人员和删除人员在实现上来说是一样的,这里就不赘述了,可以在源码中看到。
3:打印所有人员
主要是考虑类别和数据对齐问题,比较简单。

void allpeoplePrint(Contact* p)
{
	int a = 0;
	printf("%-10s\\t %-s\\t %-s\\t %-12s\\t %-25s\\n",
		"姓名",
		"性别",
		"年龄",
		"电话",
		"地址");
	for (a = 0; a < p->count; a++)//使用循环遍历打印
	{
		printf("%-10s\\t %-c\\t %-d\\t %-12s\\t %-25s\\n",
			(p->can + a)->name,
			(p->can + a)->sex,
			(p->can + a)->age,
			(p->can + a)->number,
			(p->can + a)->address);
	}
}

4:对所有人员按照名字排序

博主之前的博客是讲解过qsort函数的使用的,这里我们使用qsort函数实现就比较简单。
不太懂qsort函数的童鞋可以点击下方链接学习哦!
qsort函数的使用

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


void allpeopleSort(Contact* p)
{
	qsort(p->can, p->count, sizeof(*(p->can)), compare);

}
源码分享

.h文件:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
enum functions //使用枚举常量,让开发者可以清楚switch时每个对应的功能
{
	EXIT,
	ADD,
	DEL,
	MODIFY,
	SEARCH,
	PRINT,
	SORT
};
typedef struct people//people的大小是88字节
{
	char name[10];
	char sex;
	char address[25];
	int age;
	char number[12];
}people;


typedef struct Contact
{
	people* can;//存放通讯录成员的容器指针
	int count;//通讯录的长度
	int max;
}Contact;


extern void InitContact(Contact* Contactlist)
{
	Contactlist->can = (people*)malloc(sizeof(*(Contactlist->can))*10);//动态内存申请
	Contactlist->count = 0;
	Contactlist->max = 10;
}


void peopleAdd(Contact* p)
{
	char name1[10];
	char sex1;
	char address1[25];
	int age1;
	char number1[12];	
	if (p->count == p->max)//通讯录已满,需要调整通讯录大小
	{
		people *tmp = realloc(p->can, (p->max) * 2);//调整为原来的二倍
		if (tmp == NULL)
		{
			perror("room");
			return;
		}
		else//使原指针指向新空间
		{
			p->can = tmp;
			(p->max) *= 2;//通讯录长度自然加长为原来二倍
		}
	}

	printf("请输入姓名:");
	scanf("%s", name1);
	printf("请输入性别:");
	scanf(" %c", &sex1);
	printf("请输入年龄:");
	scanf("%d", &age1);
	printf("请输入电话:");
	scanf("%s", number1);
	printf("请输入地址:");
	scanf("%s", address1);

	strcpy((p->can + (p->count))->name, name1);
	(p->can + (p->count))->sex = sex1;
	(p->can + (p->count))->age = age1;
	strcpy((p->can + (p->count))->number, number1);
	strcpy((p->can + (p->count))->address, address1);
	(p->count)++;

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



void peopleDel(Contact*p)
{
	int a = 0;
	char input = 0;
	char name2[10] = { 0 };
	if (p->count == 0)
	{
		printf("当前通讯录无成员\\n");
		return ;
	}
	printf("请输入要删除人员的姓名:");
	scanf("%s", name2);
	for (a = 0; a < p->count; a++)
	{
		if (strcmp(name2, (p->can + a)->name)==0)
		{
			printf("是否要删除此成员?(y/n)\\n");
			scanf(" %c", &input);
			if (input == 'y')
			{
				for (int b = a; b < p->count - 2; b++)
				{
					*(p->can + b) = *(p->can + b + 1);
				}
				printf("删除成功!\\n");
				p->count--;
				return;
			}
			else 
				return;
		}
		if (a == p->count-1)
		{
			printf("查无此人!\\n");
		}
	}
}



void peopleModify(Contact* p)
{
	char name[10];
	char sex;
	char address[25];
	int age;
	char number[12];
	int a = 0;
	if (p->count == 0)
	{
		printf("当前通讯录无成员\\n");
		return;
	}
	else
	{
		printf("请输入要修改人员的姓名:");
		scanf("%s", name);
		for (a = 0; a < p->count; a++)
		{
			if (strcmp(name, (p->can + a)->name) == 0)
			{
				printf("请输入要修改后的名字:");
				scanf("%s", name);
				printf("请输入要修改后的性别:");
				scanf(" %c", &sex);
				printf("请输入要修改后的年龄:");
				scanf("%d", &age);
				printf("请输入要修改后的电话:");
				scanf("%s", number);
				printf("请输入要修改后的地址:");
				scanf("%s", address);


				strcpy((p->can + a)->name, name);
				(p->can + a)->sex = sex;
				(p->can + a)->age = age;
				strcpy((p->can + a)->number, number);
				strcpy((p->can + a)->address, address);
			}
			
			if (a == p->count)
			{
				printf("查无此人!\\n");
			}
		}
	}
}




void peopleSearch(Contact* p)
{
	char name[10] = { 0 };
	int a = 0;
	if (p->count == 0)
	{
		printf("当前通讯录无成员\\n");
		return;
	}
	else
	{
		printf("请输入要查找人员的姓名:");
		scanf("%s", name);
		for (a = 0; a < p->count; a++)
		{
			if (strcmp(name, (p->can + a)->name) == 0)
			{
				printf("%-10s\\t %-s\\t %-s\\t %-12s\\t %-25s\\n",
					"姓名",
					"性别",
					"年龄",
					"电话",
					"地址");
				printf("%-10s\\t %-c\\t %-d\\t %-12s\\t %-25s\\n",
					(p->can + a)->name,
					(p->can + a)->sex,
					(p->can + a)->age,
					(p->can + a)->number,
					(p->can + a)->address);
			}
		}
	}
}




void allpeoplePrint(Contact* p)
{
	int a = 0;
	printf("%-10s\\t %-s\\t %-s\\t %-12s\\t %-25s\\n",
		"姓名",
		"性别",
		"年龄",
		"电话",
		"地址");
	for (a = 0; a < p->count; a++)
	{
		printf("%-10s\\t %-c\\t %-d\\t %-12s\\t %-25s\\n",
			(p->can + a)->name,
			(p->can + a)->sex,
			(p->can + a)->age,
			(p->can + a)->number,
			(p->can + a)->address);
	}
}


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


void allpeopleSort(Contact* p)
{
	qsort(p->can, p->count, sizeof(*(p->can)), compare);

}

.c文件:

#include"Contact.h"

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(" 请选择 >");
}
int main()
{
	int select = 0;
	Contact Contactlist;
	InitContact(&Contactlist);//初始化通讯录
	if (Contactlist.can == NULL)
	{
		perror("room");
		return 0;
	}
	do
	{
		menu();
		scanf("%d", &select);
		
		switch (select)
		{
		case ADD:
			peopleAdd(&Contactlist);
			break;
		case DEL:
			peopleDel(&Contactlist);
			break;
		case MODIFY:
			peopleModify(&Contactlist);
			break;
		case SEARCH:
			peopleSearch(&Contactlist);
			break;
		case PRINT:
			allpeoplePrint(&Contactlist);
			break;
		case SORT:
			allpeopleSort(&Contactlist);
			break;
		case EXIT:
			free(Contactlist.can);//释放堆空间
			Contactlist.can 以上是关于300行C代码完成动态通讯录管理的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp Atlas300代码片段

C语言实现通讯录管理系统(结构体+枚举+动态内存开辟+文件操作+线性表存放数据)

异常和TCP通讯

使用 Exchange 命令行管理程序查看动态通讯组的成员

c语言实现通讯录-动态可存储版(新手向多图详细预警)

如何管理在每个 git 版本中添加私有代码片段?