资讯专栏INFORMATION COLUMN

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

PingCAP / 3876人阅读

摘要:本篇文章将用语言代码实现一个通讯录管理系统,本片文章博主将会运用到架构提,枚举,动态内存开辟和文件操作等。这里存放数据的结构是线性表。这个指针就可以通过动态开辟内存来调整存放信息的大小。扩容成功这样就实现了检查通讯录是否需要扩容的函数。

本篇文章将用C语言代码实现一个通讯录管理系统,本片文章博主将会运用到架构提,枚举,动态内> 存开辟和文件操作等。这里存放数据的结构是线性表。

博主码云gitee链接:https://gitee.com/byte-binxin(需要源码自取)

先给大家展示一张效果图


通讯录菜单栏实现

我们要实现的通讯录应该具备增删查改四种基本功能,还有显示,排序,退出和保存的功能。所以我们会有个功能。实现如下:

void menu(){	printf("--------------------------------------/n");	printf("------------通讯录管理系统------------/n");	printf("------------1.添加联系人--------------/n");	printf("------------2.删除联系人--------------/n");	printf("------------3.查找联系人--------------/n");	printf("------------4.更改联系人信息----------/n");	printf("------------5.显示通讯录--------------/n");	printf("------------6.对联系人进行排序--------/n");	printf("------------7.保存通讯录--------------/n");	printf("------------0.退出通讯录--------------/n");	printf("--------------------------------------/n");}

打印效果如下:

线性表的创建

我们可以先创建一个结构体,里面包含联系人的各种信息。

#define NAME_MAX 20#define TELE_MAX 12#define SEX_MAX  5#define ADDR_MAX 50typedef struct PeoInfo{	char name[NAME_MAX];	int age;	char sex[SEX_MAX];	char tele[TELE_MAX];	char address[ADDR_MAX];}PeoInfo;

然后创建一个结构体,其中有用来存放通讯录的大小信息,通讯录的容量和一个结构体指针指向PeoInfo这个结构体。这个指针就可以通过动态开辟内存来调整存放信息的大小。

typedef struct Contact{	PeoInfo* data;	int size;	int capacity;}Contact;

初始化通讯录

为了让通讯录能够存放数据,我们需要初始化一下通讯录,首先动态开辟一个3个(根据自己来)PepInfo结构体大小的空间,然后后续根据需求再扩大容量。还要设计一个加载函数,把上一次保存的信息加载进来,这个函数我们后面部分讲解。代码实现如下:

//初始化通讯录void InitContact(Contact* pc){	assert(pc);	//开辟三个大小的空间	pc->data = (PeoInfo*)malloc(sizeof(PeoInfo)* 3);	if (pc->data==NULL)	{		printf("%s", strerror(errno));		exit(-1);	}		pc->size = 0;	pc->capacity = 3;	//加载数据到通讯录上	LoadContact(pc);}

main函数内部结构搭建

我们要让用户选择对应的操作,我们应该提供对应的实现,考虑到多种选择,我们可以用switch语句,还有为了让用户多次选择,我们可以把这个选择放到一个do-while循环里面,根据用户的选择来进行相应的操作。
为了方便之后自己更好的了解哪个对应哪个选择对功能,我们可以创建一个枚举类型,这样我们就可以一目了然哪里该实现哪个功能。

enum Option{	EXIT,	ADD,	DEL,	SEARCH,	MODIFY,	SHOW,	SORT,	SAVE};
int main(){	//创建一个通讯录	Contact con;	//初始化通讯录	InitContact(&con);		int input = 0;	do	{		//清屏		system("cls");		menu();		printf("请选择:>");		scanf("%d", &input);		switch (input)		{		case ADD:			//增加联系人函数			break;		case DEL:			//删除联系人函数			break;		case SEARCH:			//查找联系人函数			break;		case MODIFY:			//修改联系人函数			break;		case SHOW:			//显示联系人函数			break;		case SORT:			//对联系人进行排序函数			break;		case SAVE:			//保存联系人函数			break;		case EXIT:			//销毁通讯录函数  防止内存泄漏			printf("退出通讯录/n");			break;		default:			printf("选择错误/n");			system("pause");			break;		}	} while (input);	return 0;}

很显然,当用户选择0是就可以退出这个循环了,也就退出了这个程序。

实现功能函数

//初始化通讯录void InitContact(Contact* pc);//增加联系人void AddContact(Contact* pc);//删除联系人void DelContact(Contact* pc);//查找联系人void SearchContact(Contact* pc);//更改联系人信息void ModifyContact(Contact* pc);//显示联系人void ShowContact(Contact* pc);//对通讯录进行排序void SortContact(Contact* pc);//保存通讯录void SaveContact(Contact* pc);//销毁通讯录void DestoryContact(Contact* pc);

添加联系人

添加联系人要考虑通讯录容量的问题,所以每次添加联系人的时候就要检查一下通讯录的先有容量,看是否需要扩容,如果通讯录现有容量和size相同,说明通讯录满了,就要扩容了。扩容需要用到realloc函数来扩大data指针的指向空间的大小。

void CheckCapacity(Contact* pc){	if (pc->capacity == pc->size)	{		PeoInfo* tmp = (PeoInfo*)realloc(pc->data, sizeof(PeoInfo)*(pc->capacity * 2));		if (tmp == NULL)		{			printf("%s", strerror(errno));			exit(-1);		}		pc->data = tmp;		pc->capacity *= 2;		printf("扩容成功/n");	}}

这样就实现了检查通讯录是否需要扩容的函数。

void AddContact(Contact* pc){	assert(pc);	//检查容量	CheckCapacity(pc);	printf("请输入你要添加人的姓名:>");	scanf("%s", pc->data[pc->size].name);	printf("请输入你要添加人的性别:>");	scanf("%s", pc->data[pc->size].sex);	printf("请输入你要添加人的年龄:>");	scanf("%d", &(pc->data[pc->size].age));	printf("请输入你要添加人的电话号码:>");	scanf("%s", pc->data[pc->size].tele);	printf("请输入你要添加人的家庭住址:>");	scanf("%s", pc->data[pc->size].address);		pc->size++;	printf("增加成功/n");	system("pause");}

显示通讯录

为了让我们更好的观察添加联系人这个功能和其他的功能是否很好的实现了,我们先来实现一个显示通讯录函数来观察一下。
先判断参数,如果通讯录为空就打印一下通讯录为空,然后退出,否则就显示联系人,先打印通讯录信息。
打印之前还要寻找用户要查找的联系人是存在,我们先实现查找联系人的函数。

int FindPeopleByName(const Contact* pc, char name[]){	int i = 0;	for (i = 0; i < pc->size; i++)	{		if (strcmp(pc->data[i].name, name) == 0)		{			return i;		}	}	return -1;}

我们为了好看,可以搭建一个表头,通过循环来控制,可以自己根据训练次数来调节

可以通过格式化输出的"-""%x"来对齐控制,具体看一下如下代码。

//显示联系人void ShowContact(Contact* pc){	assert(pc);	if (pc->size == 0)	{		printf("通讯录为空/n");		system("pause");		return;	}	//打印横线	int j = 0;	for (j = 0; j < 21; j++)	{		printf("——");	}	printf("/n");	printf("|%42s/t/t/t/t/t/t/b/b/b/b/b|/n", "通讯录");	for (j = 0; j < 21; j++)	{		printf("——");	}	printf("/n");	//打印标题	printf("|%-15s|%-5s|%-5s|%-12s|%-42s/b|/n", "姓名", "性别", "年龄", "电话", "家庭住址");	//打印信息	int i = 0;	for (i = 0; i < pc->size; i++)	{		for (j = 0; j < 21; j++)		{			printf("——");		}		printf("/n");		printf("|%-15s|%-5s|%-5d|%-12s|%-42s/b|/n",			pc->data[i].name,			pc->data[i].sex,			pc->data[i].age,			pc->data[i].tele,			pc->data[i].address);	}	for (j = 0; j < 21; j++)	{		printf("——");	}	printf("/n");	system("pause");}

下面我们先来看一下添加联系人功能的效果:

删除联系人

删除联系人的第一步首先要检查参数,看通讯录是否为空,空就返回,无法删除,不为空就要查找联系人,看这个联系人是否存在,在哪个位置,这些都是我们需要考虑的,查找联系人的函数在上面我们已经实现过来,这里就不过多介绍。
接下来就是删除了,有两种方式:
第一种相对来说比较简单,就是就通讯录中最后一个人挪动到要删除的那个人的位置,但这样就有一个缺点就是通讯录的顺序发生了改变。
另一种方法相对来说比较麻烦,但其实也很简单,就是把钥删除的位置后面的联系人都往前挪动一个就可以了,具体实现如下:

//删除联系人void DelContact(Contact* pc){	assert(pc);	if (pc->size == 0)	{		printf("通讯录为空/n");		system("pause");		return;	}	else	{		char name[NAME_MAX];		printf("请输入你要删除联系人的姓名:>");		scanf("%s", name);		//查找联系人		int pos = FindPeopleByName(pc,name);		if (pos == -1)		{			printf("该联系人不存在/n");			printf("删除失败/n");			system("pause");		}		else		{			//删除			int i = 0;			for (i = pos; i < pc->size - 1; i++)			{				pc->data[i] = pc->data[i + 1];			}			pc->size--;			printf("删除成功/n");			system("pause");		}	}}

动态效果图如下:

查找联系人

查找联系人就是由要用到上面的查找函数,找到后把这个信息打印一遍就可以了。

//查找联系人void SearchContact(Contact* pc){	assert(pc);	if (pc->size == 0)	{		printf("通讯录为空/n");		system("pause");		return;	}	else	{		char name[NAME_MAX];		printf("请输入你要查找联系人的姓名:>");		scanf("%s", name);		//查找联系人		int pos = FindPeopleByName(pc, name);		if (pos == -1)		{			printf("该联系人不存在/n");			printf("查找失败/n");			system("pause");		}		else		{			printf("查找成功/n");			//打印			int j = 0;			for (j = 0; j < 21; j++)			{				printf("——");			}			printf("/n");			//打印标题			printf("|%-15s|%-5s|%-5s|%-12s|%-42s/b|/n", "姓名", "性别", "年龄", "电话", "家庭住址");			for (j = 0; j < 21; j++)			{				printf("——");			}			printf("/n");			printf("|%-15s|%-5s|%-5d|%-12s|%-42s/b|/n",				pc->data[pos].name,				pc->data[pos].sex,				pc->data[pos].age,				pc->data[pos].tele,				pc->data[pos].address);			for (j = 0; j < 21; j++)			{				printf("——");			}			printf("/n");			system("pause");		}	}}

动态效果演示如下:

更改联系人信息

我们先创建一个简易的菜单栏来提示用户要对哪个人的哪个信息进行修改。

void ModifyMenu(){	printf("---------------------------/n");	printf("-----1.姓名     2.性别-----/n");	printf("-----3.年龄     4.电话-----/n");	printf("-----5.家庭住址 0.退出-----/n");	printf("---------------------------/n");}

然后我们可以在ModifyContact函数里面调用,与主函数内部的框进搭建有相似之处,我们来一起看看代码是如何实现的:

//更改联系人信息void ModifyContact(Contact* pc){	assert(pc);	if (pc->size == 0)	{		printf("通讯录为空/n");		system("pause");		return;	}	else	{		char name[NAME_MAX];		printf("请输入你要更改的联系人的姓名:>");		scanf("%s", name);		//查找联系人		int pos = FindPeopleByName(pc, name);		if (pos == -1)		{			printf("该联系人不存在/n");			printf("更改信息失败/n");			system("pause");		}		else		{			int input = 0;						do			{				system("cls");				ModifyMenu();				printf("请选择:>");				scanf("%d", &input);				switch (input)				{				case 1:					printf("请输入修改后的姓名:>");					scanf("%s", pc->data[pos].name);					printf
            
                     
             
               

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/121282.html

相关文章

  • C语言----实现动态通讯

    摘要:文章目录前言前言一建立文件二编写函数三调试运行四成果展示五代码汇总总结前言通讯录是我们日常手机中常见的功能之一,综合语言中结构体,循环,条件语句,动态内存分配等等知识点,我们对手机通讯录进行一个简单的实现,下面我们开始讲解准备工作利用语 文章目录 前言一、建立文件二、编写函数三、调试运...

    whlong 评论0 收藏0
  • C语言进阶】C语言实现通讯 升级版 { 含动态扩容/销毁/信息保存功能 }(强烈建议收藏食用)

    摘要:之前的通讯录在程序退出后内部的数据就会消失,再次打开程序后只能重新输入数据,为此我们增加了一个保存功能来保存信息。 前言: 由于之前实现的通讯录在存储方面只能支持静态的1000人的存储量,但是如果联系人较少,则会造成较大的内存浪费。而当联系人一旦超过1000时,就不能再继续存储信息了。因...

    gxyz 评论0 收藏0
  • C语言中还有这些类型,别再说你不知道了!手把手带你解锁C语言中的自定义类型,让你写你所想。

    摘要:结构体类型的特殊声明在初阶结构体中,我们已经将了结构体类型是如何进行声明的,那么在这里,我们将讲一些特殊的结构体声明不完全的声明。所以我们应该这样写通过指针来找到下一个同类型结构体的写法,我们就称之为结构体的自引用。 ...

    hizengzeng 评论0 收藏0
  • 动态文件通讯C语言中的文件的读写操作

    摘要:那么我们首先来改造储存空间也就是通讯录结构体静态版本人信息存放在数组中统计存放的人数动态版本统计存放的人数有效容量我们将原本的结构体数组改为一个结构体指针,以此来维护用以储存个人信息的空间。 上一期我们编写了一个C语言版本的简易通讯录,但是我们的之前的通讯录是没有记忆功能的,也就是说,一旦关...

    h9911 评论0 收藏0
  • ❤️C语言通讯管理系统(简易版)❤️

    ❤️C语言通讯录管理系统(简易版)❤️ ?一、通讯录?二、菜单实现和用户交互?三、主函数⭐️⭐️1.enum选项⭐️⭐️2.switch判断 ?四、定义联系人和通讯录⭐️⭐️1.定义联系人结构体⭐️⭐️2.定义通讯录结构体⭐️⭐️3.定义结构体变量 ?五、通讯录初始化?六、新增联系人?七、查找联系人?八、删除联系人?九、修改联系人?十、查看所有联系人?十一、清空所有联系人?十二、以名字排序所有...

    justCoding 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<