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