【C】动态顺序表实现通讯录

  上一篇讲到了静态顺序表实现通讯录,显然这种实现方式是有缺陷的,比如结构体中的数组大小过大,会造成内存浪费,但是如果给数组开辟的内存过小,又会面临无法扩大容量的问题,接下来介绍一种动态顺序表实现通讯录的方法。

头文件

  contact.h

# ifndef __CONTACT_H__
# define __CONTACT_H__

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

//通讯录系统基本操作
enum OPTION
{
	QUIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	EMPTY,
	SORT
};

//修改通讯录信息
enum MODIFY
{
	EXIT,
	NAME,
	AGE,
	SEX,
	TELE,
	ADDRESS
};

//排序
enum SORT
{
	BACK,
	NAME_SORT,
	AGE_SORT
};

# define MAX_SEX 5
# define MAX_TELEPHONE 12
# define MAX_NAME 20
# define MAX_ADDRESS 20
# define DEFAULT_CAPACITY 3
# define ADD_CAPACITY 2

//个人信息
typedef struct PeoInfo
{
	int age;
	char sex[MAX_SEX];
	char tele[MAX_TELEPHONE];
	char name[MAX_NAME];
	char address[MAX_ADDRESS];
}PeoInfo;

//通讯录信息
typedef struct Contact
{
	PeoInfo * data; //指向一块动态开辟的内存空间
	int count; //当前录入信息的人数
	int capacity; //通讯录信息的最大容量
}Contact, *pContact;

void InitContact(pContact pc); //初始化通讯录
void CheckCapacity(pContact pc); //扩大容量
void AddContact(pContact pc); //添加个人信息
void ShowContact(pContact pc); //显示通讯录中的个人信息
int FindContactIndex(char name[], pContact pc); //查找通讯录个人信息的下标
void SearchContact(pContact pc); //查找通讯录的个人信息
void DeleteContact(pContact pc); //删除通讯录中的个人信息
void ModifyContact(pContact pc); //修改通讯录中的个人信息
void BubbleSortName(pContact pc); //排序姓名
void BubbleSortAge(pContact pc); //排序年龄
void SortContact(pContact pc); //排序通讯录中的个人信息
void EmptyContact(pContact pc); //清空通讯录中的个人信息
void DestoryContact(pContact pc); //销毁通讯录

#endif //__CONTACT_H__

源代码

1.contact.c

#define _CRT_SECURE_NO_WARNINGS 1

/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:contact.c
* 功能:通讯录系统内部实现细节(顺序表之动态开辟内存)
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年5月11日14:22:26
*/

# include "contact.h"

/*
*	函数名称:InitContact
*
*	函数功能:初始化通讯录信息
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void InitContact(pContact pc)
{
	assert(NULL != pc);

	Sleep(1000);

	pc->count = 0;
	pc->capacity = DEFAULT_CAPACITY;
	pc->data = (PeoInfo *)calloc(sizeof(PeoInfo), pc->capacity);

	if (NULL != pc->data)
	{
		printf("初始化通讯录成功!\n");
	}
	else
	{
		perror("初始化通讯录失败!\n");
		exit(-1);
	}

	return;
}

/*
*	函数名称:CheckCapacity
*
*	函数功能:检查是否需要增大容量
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void CheckCapacity(pContact pc)
{
	assert(NULL != pc);

	if (pc->count == pc->capacity)
	{
		PeoInfo * pNew = (PeoInfo *)realloc(pc->data, sizeof(PeoInfo)*(pc->capacity + ADD_CAPACITY));

		if (NULL != pNew)
		{
			pc->data = pNew;
			//pNew的地址赋给了pc->data,此时不需要pNew了
			pNew = NULL;
		}
		else
		{
			perror("扩大容量失败!\n");
			exit(-1);
		}

		pc->capacity += ADD_CAPACITY;
		printf("扩大容量成功!\n");
	}
	else
	{
		;
	}

	return;
}

/*
*	函数名称:AddContact
*
*	函数功能:添加个人信息
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void AddContact(pContact pc)
{
	assert(NULL != 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].sex);
	printf("请输入电话:>");
	scanf("%s", pc->data[pc->count].tele);
	printf("请输入地址:>");
	scanf("%s", pc->data[pc->count].address);
	printf("恭喜添加成功!\n");

	pc->count++;

	return;
}

/*
*	函数名称:ShowContact
*
*	函数功能:显示通讯录信息
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void ShowContact(pContact pc)
{
	int i = 0;

	assert(NULL != pc);

	if (0 == pc->count)
	{
		printf("通讯录为空!\n");
		exit(0);
	}
	else
	{
		printf("|----------+-----+-----+------------+----------|\n");
		printf("%-10s %-5s %-5s %-12s %-10s\n", "|name", "|age", "|sex", "|tele", "|address   |");
		printf("|----------+-----+-----+------------+----------|\n");
		for (i=0; i<pc->count; i++)
		{
			printf("|%-10s %-5d %-5s %-12s %-10s\n",
				  pc->data[i].name, pc->data[i].age, pc->data[i].sex,
				  pc->data[i].tele, pc->data[i].address);
			printf("|----------+-----+-----+------------+----------|\n");
		}
	}
	
	return;
}

/*
*	函数名称:FindContactIndex
*
*	函数功能:查找通讯录个人信息的下标(通过姓名查找)
*
*	入口参数:name, pc
*
*	出口参数:i or -1
*
*	返回类型:int
*/

int FindContactIndex(char name[], pContact pc)
{
	int i = 0;
	
	assert(NULL != pc);

	for (i=0; i<pc->count; i++)
	{
		if (0 == strcmp(pc->data[i].name, name))
		{
			//找到后返回当前位置
			return i;
		}
		else
		{
			;
		}
	}

	return -1;
}

/*
*	函数名称:SearchContact
*
*	函数功能:查找通讯录个人信息(通过姓名查找)
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void SearchContact(pContact pc)
{
	int index = 0;
	char name[MAX_NAME] = {0};

	assert(NULL != pc);
	
	printf("请输入要查找的人的名字:>");
	scanf("%s", name);

	index = FindContactIndex(name, pc);

	if (-1 == index)
	{
		printf("要查找的人不存在!\n");
	}
	else
	{
		printf("|----------+-----+-----+------------+----------|\n");
		printf("%-10s %-5s %-5s %-12s %-10s\n", "|name", "|age", "|sex", "|tele", "|address   |");
		printf("|----------+-----+-----+------------+----------|\n");
		printf("|%-10s %-5d %-5s %-12s %-10s\n",
		pc->data[index].name, pc->data[index].age, pc->data[index].sex,
		pc->data[index].tele, pc->data[index].address);
		printf("|----------+-----+-----+------------+----------|\n");
	}	

	return;
}

/*
*	函数名称:DeleteContact
*
*	函数功能:删除通讯录个人信息
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void DeleteContact(pContact pc)
{
	int index = 0;
	int i = 0;
	char name[MAX_NAME] = {0};
	
	assert(NULL != pc);

	if (0 == pc->count)
	{
		printf("通讯录为空!\n");
		exit(-1);
	}
	else
	{
		printf("请输入要删除的人的名字:>");
		scanf("%s", name);
		//查找
		index = FindContactIndex(name, pc);

		if (-1 == index)
		{
			printf("要删除的人不存在!\n");
		}
		else
		{
			//删除
			for (i=index; i<pc->count-1; i++)
			{
				//后一个替换前一个,达到删除的目的
				pc->data[i] = pc->data[i+1];
			}

			pc->count--;

			printf("恭喜删除成功!\n");
		}
	}

	return;
}

/*
*	函数名称:ReviseMenu
*
*	函数功能:修改通讯录信息菜单显示
*
*	入口参数:void
*
*	出口参数:select
*
*	返回类型:int
*/

int ReviseMenu(void)
{
	int select = 0;

	printf("************************************\n");
	printf("*******  欢迎修改通讯录信息  *******\n");
	printf("*******  1. 姓名    2. 年龄  *******\n");
	printf("*******  3. 性别    4. 电话  *******\n");
	printf("*******  5. 地址    0. 退出  *******\n");
	printf("************************************\n");
	printf("select>");

	assert(1 == scanf("%d", &select));

	return select;
}

/*
*	函数名称:ModifyContact
*
*	函数功能:修改通讯录中的个人信息
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void ModifyContact(pContact pc)
{
	int index = 0;
	char name[MAX_NAME] = {0};

	assert(NULL != pc);

	printf("请输入要修改的人的名字:>");
	scanf("%s", name);

	index = FindContactIndex(name, pc);

	if (0 == pc->count)
	{
		printf("通讯录为空!\n");
		exit(-1);
	}
	else if (-1 == index)
		{
			printf("要修改的人不存在!\n");
		}
		else
		{
			int select = ReviseMenu();

			switch (select)
			{
				case EXIT:
					printf("退出修改!\n");
					break;
				case NAME:
					printf("修改姓名:>");
					scanf("%s", pc->data[index].name);
					printf("修改姓名成功!\n");
					break;
				case AGE:
					printf("修改年龄:>");
					scanf("%d", &(pc->data[index].age));
					printf("修改年龄成功!\n");
					break;
				case SEX:
					printf("修改性别:>");
					scanf("%s", pc->data[index].sex);
					printf("修改性别成功!\n");
					break;
				case TELE:
					printf("修改电话:>");
					scanf("%s", pc->data[index].tele);
					printf("修改电话成功!\n");
					break;
				case ADDRESS:
					printf("修改地址:>");
					scanf("%s", pc->data[index].address);
					printf("修改地址成功!\n");
					break;
				default:
					printf("输入有误,返回上一级!\n");
					break;
			}
		}

	return;
}

/*
*	函数名称:SortMenu
*
*	函数功能:通讯录信息排序菜单显示
*
*	入口参数:void
*
*	出口参数:select
*
*	返回类型:int
*/

int SortMenu(void)
{
	int select = 0;

	printf("************************************\n");
	printf("*******  欢迎排序通讯录信息  *******\n");
	printf("*******  1. 姓名    2. 年龄  *******\n");
	printf("*******       0. 退出        *******\n");
	printf("************************************\n");
	printf("select>");

	assert(1 == scanf("%d", &select));

	return select;
}

/*
*	函数名称:BubbleSortName
*
*	函数功能:排序姓名
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void BubbleSortName(pContact pc)
{
	int i = 0;
	int flag = 1;

	assert(NULL != pc);

    for (i=0; (i<pc->count-1) && (flag); i++)
    {
		int j = 0;
		flag = 0;

		for (j=0; j<pc->count-1-i; j++)
        {
			if (strcmp(pc->data[j].name, pc->data[j+1].name) > 0)
            {
                PeoInfo tmp = pc->data[j];
                pc->data[j] = pc->data[j+1];
                pc->data[j+1] = tmp;
				flag = 1;
            }
			else
			{
				;
			}
        }
    }	

	return;
}

/*
*	函数名称:BubbleSortAge
*
*	函数功能:排序姓名
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void BubbleSortAge(pContact pc)
{
	int i = 0;
	int flag = 1;

	assert(NULL != pc);

    for (i=0; (i<pc->count-1) && (flag); i++)
    {
		int j = 0;
		flag = 0;

		for (j=0; j<pc->count-1-i; j++)
        {
			if (pc->data[j].age > pc->data[j+1].age)
            {
                PeoInfo tmp = pc->data[j];
                pc->data[j] = pc->data[j+1];
                pc->data[j+1] = tmp;
				flag = 1;
            }
			else
			{
				;
			}
        }
    }	

	return;
}

/*
*	函数名称:SortContact
*
*	函数功能:排序通讯录中的个人信息
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void SortContact(pContact pc)
{
	assert(NULL != pc);

	if (0 == pc->count)
	{
		printf("通讯录为空!\n");
		exit(-1);
	}
	else
	{
		int select = SortMenu();

		switch (select)
		{
			case BACK:
				printf("退出排序!\n");
				break;
			case NAME_SORT:
				printf("排序姓名:>");
				BubbleSortName(pc);
				printf("排序姓名成功!\n");
				break;
			case AGE_SORT:
				printf("修改年龄:>");
				BubbleSortAge(pc);
				printf("排序年龄成功!\n");
				break;
			default:
				printf("输入有误,返回上一级!\n");
				break;
		}
	}

	return;
}

/*
*	函数名称:EmptyContact
*
*	函数功能:清空通讯录个人信息
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void EmptyContact(pContact pc)
{
	assert(NULL != pc);

	pc->count = 0;
	pc->capacity = 0;

	memset(pc->data, 0, sizeof(pc->data));

	printf("清空通讯录成功!\n");

	return;
}

/*
*	函数名称:DestoryContact
*
*	函数功能:销毁通讯录
*
*	入口参数:pc
*
*	出口参数:void
*
*	返回类型:void
*/

void DestoryContact(pContact pc)
{
	Sleep(1000);

	free(pc->data);
	pc->data = NULL;
	pc->capacity = 0;
	pc->count = 0;

	printf("销毁成功!\n");

	return;
}

2.test.c

#define _CRT_SECURE_NO_WARNINGS 1

/*
* Copyright (c) 2018, code farmer from sust
* All rights reserved.
*
* 文件名称:test.c
* 功能:通讯录主程序
*
* 当前版本:V1.0
* 作者:sustzc
* 完成日期:2018年5月11日14:24:43
*/

# include "contact.h"

/*
*	函数名称:MainMenu
*
*	函数功能:通讯录主菜单显示
*
*	入口参数:void
*
*	出口参数:choose
*
*	返回类型:int
*/

int MainMenu(void)
{
	int choose = 0;

	printf("************************************\n");
	printf("*******  欢迎来到通讯录系统  *******\n");
	printf("*******  1. 添加    2. 删除  *******\n");
	printf("*******  3. 查找    4. 修改  *******\n");
	printf("*******  5. 显示    6. 清空  *******\n");
	printf("*******  7. 排序    0. 退出  *******\n");
	printf("************************************\n");
	printf("choose>");

	assert(1 == scanf("%d", &choose));

	return choose;
}

/*
*	函数名称:main
*
*	函数功能:通讯录主程序
*
*	入口参数:void
*
*	出口参数:0
*
*	返回类型:int
*/

int main(void)
{
	int choose = 0;
	Contact my_con;
	InitContact(&my_con);

	do
	{
		choose = MainMenu();

        switch(choose)
		{
			case QUIT:
				printf("正在退出通讯录系统!\n");
				DestoryContact(&my_con);
				break;
			case ADD:
				AddContact(&my_con);
				break;
			case DEL:
				DeleteContact(&my_con);
				break;
			case SEARCH:
				SearchContact(&my_con);
				break;
			case MODIFY:
				ModifyContact(&my_con);
				break;
			case SHOW:
				ShowContact(&my_con);
				break;
			case EMPTY:
				EmptyContact(&my_con);
				break;
			case SORT:
				SortContact(&my_con);
				break;
			default:
				printf("输入有误,请重新输入!\n");
				break;
		}
	}while(choose);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/sustzc/article/details/80507236