动态内存开辟版简易通讯录

上条只是一个动态开辟的简单实现,但是要存储的大于1000个人呢?这时候就想到了动态开辟内存
思路:增加了容量这个变量来判断是否需要进行内存的开辟

代码如下:
//contact.h

#ifndef __CONTACT_H__
#define __CONTACT_H__
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
enum OPTION
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT,
	EMPTY
};
enum Modify           
{
	EXIT1,
	NAME,
	AGE,
	TEL,
	ADDR,
	SEX
	
};
#define MAX_NAME 20 
#define MAX_SEX 5
#define MAX_TEL 50
#define MAX_ADDR 100
#define MAX 1000
#define DEFAULT_SZ 3
typedef struct PeoInfo       //用数组存放通讯录中的人数,而人的信息用结构体存储
{
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tel[MAX_TEL];
	char addr[MAX_ADDR];
}PeoInfo;

typedef struct Contact     //此结构体存放要修改的数组和记录当前元素的个数变量
{
	PeoInfo *data ;    
	int count ;     //存放当前元素的个数
	int capacity;   //最大容量
}Contact,*pContact ;      //Contact是一种类型,对struct Contact *进行了类型重命名,则pContact是一种指针类型,如同int *



void InitContact(pContact pc);     //初始化数组和count

void AddContact(pContact pc );     //添加

int find(pContact pc);             //查找指定联系人的信息

void DelContact(pContact pc);      //删除

void SearchContact(pContact pc);   //查找

void ModifyContact(pContact pc);   //修改

void ShowContact(pContact pc);     //显示

void SortContact(pContact pc);     //排序

void EmptyContact(pContact pc);    //清空

void DestroyContact(pContact pc);  //销毁

void CheckCapacity(pContact pc);    //判断是否需要增容

#endif // !__CONTACT_H__
//contact.c
#include"contact.h"
void Modifymenu()
{
	printf("**********************\n");
	printf("*******  1.NAME ******\n");
	printf("*******  2.AGE  ******\n");
	printf("*******  3.TEL  ******\n");
	printf("*******  4.ADDR ******\n");
	printf("*******  5.SEX  ******\n");
	printf("*******  0.EXIT1******\n");
}
void InitContact(pContact pc) //初始化数组和count
{
	pc->count = 0;
	pc->capacity = DEFAULT_SZ;
	pc->data = (PeoInfo*)calloc((pc->capacity),sizeof(PeoInfo) );
}

void  CheckCapacity(pContact pc)   //用函封装起来
{
	//增加扩容的想法,思路:刚开始动态开辟3个内存空间,之后,每添加一个人就会扩容2个对应的内存空间
	//进行添加操作(先判断是否需要增容)
	if (pc->count == pc->capacity)
	{
		PeoInfo * p = (PeoInfo *)realloc(pc->data, (pc->capacity + 2)*sizeof(PeoInfo));
		//进行重新调整大小realloc(内存块地址,多大空间)
		if (p != NULL)      
			//realloc之后,不一定是在原来空间的后面直接进行追加的,可能是重新开辟,有可能开辟成功,也有可能开辟失败,当开辟失败的时候,指向为空,只要开辟成功,就可以让原来指向这块空间的指针继续维护它。
		{
			pc->data = p;
			p = NULL;          //防止p成为野指针
		}
		pc->capacity += 2;
		printf("增容成功\n");
	}
	
}
void AddContact(pContact pc)  //添加
{
	
	CheckCapacity(pc);
	printf("请输入名字->");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入年龄->");
	scanf("%d", &(pc->data[pc->count].age));
	printf("请输入电话->");
	scanf("%s", pc->data[pc->count].tel);
	printf("请输入地址->");
	scanf("%s", pc->data[pc->count].addr);
	printf("请输入性别->");
	scanf("%s", pc->data[pc->count].sex);
	pc->count++;
}

int  Find(pContact pc)          ///查找指定联系人的信息
{
	int i = 0;
	char name[MAX_NAME];
	printf("请输入要查找联系人的姓名->\n");
	scanf("%s", name);
	for (i = 0; i < pc->count; i++)
	{
		if (strcmp(name, pc->data[i].name) == 0)
		{
			return i;              //查找成功返回下标
		}
		
	}
	return -1;                   //跳出循环说明没有找到,返回-1
}
void DelContact(pContact pc)  //删除
{
	int i = 0;
	if (pc->count == 0)
	{
		printf("通讯录为空\n");
		return;
	}

   //删除操作,在进行删除操作时,先要进行查找这个联系人,如果这个联系人存在才能进行删除,否则不能删除
	int ret = Find(pc);        //用一个变量接收函数返回值,如果返回不为-1,就说明可以进行删除操作
	if (ret != -1)            //可以进行删除操作,删除操作的本质是让数组-1,count-1,所查找的联系                            人,而返回的ret为该下标值,怎么删掉这个值呢?,就是把后面的值往前挪
	{
		for (i = ret; i < pc->count -ret- 1; i++)         //往前挪
		{
			pc->data[i] = pc->data[i + 1];
		}
		pc->count--;
		printf("删除成功\n");
	}
	else
	{
		printf("该联系人不存在\n");
	}

}

void ShowContact(pContact pc)  //显示
{
	int i = 0;
	if (pc->count == 0)
	{
		printf("通讯录为空\n");
		return;
	}
	for (i = 0; i < pc->count; i++)
	{
		printf("%-5s  %-3d  %-5s  %-11s  %-5s", pc->data[i].name, pc->data[i].age, pc->data[i].sex,pc->data[i].tel,pc->data[i].addr);
		printf("\n");
	}
	printf("———————————————————\n");
}


void SearchContact(pContact pc)   //查找  
{
	//查找联系人,查找完成后显示联系人的信息
	int ret = Find(pc);
	if (ret != -1)
	{
		printf("姓名: %s  年龄: %d  性别: %s  电话:  %s  地址:  %s\n", pc->data[ret].name, pc->data[ret].age, pc->data[ret].sex, pc->data[ret].tel, pc->data[ret].addr);
	}
	else
	{
		printf("查找失败,该联系人不存在\n");
		return;
	}
	printf("———————————————————\n");
}

void ModifyContact(pContact pc)    //修改
{
	//修改时,先要进行查询,判断联系人是否存在
	int ret = Find(pc);
	int input = 0;
	if (ret != -1)
	{
		Modifymenu();
		printf("请输入要修改的信息->");
		scanf("%d", &input);
		switch (input)
		{
		case NAME:
			printf("请输入修改后的姓名->");
			scanf("%s", pc->data[ret].name);
			break;
		case AGE:
			printf("请输入修改后的年龄->");
			scanf("%d", &(pc->data[ret].age));
			break;
		case SEX:
			printf("请输入修改后的性别->");
			scanf("%s", pc->data[ret].sex);
			break;
		case TEL:
			printf("请输入修改后的电话->");
			scanf("%s", pc->data[ret].tel);
			break;
		case ADDR:
			printf("请输入修改后的地址->");
			scanf("%s", pc->data[ret].addr);
			break;
		case EXIT1:
			break;
		default:
			printf("输入错误\n");
			break;
		}	
		printf("修改成功\n");
	}
	else
	{
		printf("该联系人不存在\n");
		return;
	}

}

void SortContact(pContact pc)     //排序,以名字的方式排序
{
	//采用冒泡排序
	int i = 0;
	int j = 0;
	for (i = 0; i < pc->count - 1; i++)
	{
		for (j = 0; j < pc->count - 1; j++)
		{
			if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
			{
				PeoInfo tmp;   //定义一个同样类型的变量
				tmp = pc->data[j];
				pc->data[j] = pc->data[j + 1];
				pc->data[j + 1] = tmp;
			}
		}
	}
	printf("排序完成\n");
	printf("———————————————————\n");
	ShowContact(pc);
	printf("———————————————————\n");

}


void EmptyContact(pContact pc)    //清空
{
	memset(pc->data, 0, sizeof(pc->data));
	pc->count = 0;
	printf("清空成功\n");
	printf("———————————————————\n");

}

void DestroyContact(pContact pc)  //销毁
{
	free(pc->data);
	pc->data = NULL;
	pc->count = 0;
	pc->capacity = 0;
}

//test.c


#include"contact.h"

void menu()
{
	printf("*********************************\n");
	printf("**** 1.add          2.del    ****\n");
	printf("**** 3.search       4.modify ****\n");
	printf("**** 5.show         6.sort   ****\n");
	printf("**** 7.empty        0.exit   ****\n");
	printf("*********************************\n");

}
int main()
{
	int input = 0;
	Contact my_con;
	InitContact(&my_con);
	
	do
	{

		menu();
		printf("请选择->");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&my_con);    //传入的是地址
			break;
		case DEL:
			DelContact(&my_con);
			break;
		case SEARCH:
			SearchContact(&my_con);
			break;
		case MODIFY:
			ModifyContact(&my_con);
			break;
		case SHOW:
			ShowContact(&my_con);
			break;
		case SORT:
			SortContact(&my_con);
			break;
		case EMPTY:
			EmptyContact(&my_con);
			break;
		case EXIT:
			DestroyContact(&my_con);
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}

	} while (input);
	return 0;
}


 
  
 


这里只显示增加后的功能


猜你喜欢

转载自blog.csdn.net/miqingzhiwen/article/details/80297313