在上一篇文章中,介绍了静态存储通讯录的方式,考虑到它在实际运用中存在的问题,接下来就在原有的基础上进行改造。
- 首先,我们思考,当我们想要动态进行存储时,那么我们就得动态开辟空间,既然是可以变化的空间,那么我们就得有一个判断有效元素个数与空间容量的比较,当有效元素个数达到空间容量时,就得进行扩容操作。
静态时通讯录结构体为
typedef struct Contact
{
Peoinfo data[MAX];
int sz;
}Contact;
- 基于以上分析,需加入一个新的变量来记录空间容量大小
动态时通讯录结构体为
typedef struct Contact
{
PeoInfo* data;
int sz;//有效元素的个数
int capacity;//容量
}Contact;
- 其次,什么时刻该进行扩容呢?我们就得新增一个检查函数,比较有效元素与空间容量的大小,以此来判定是否进行扩容。
void CheckCapacity(Contact* pcon)
{
if(pcon->sz == pcon->capacity)
{
//每次扩容双倍
PeoInfo* ptr = realloc(pcon->data, (pcon->capacity * 2)*sizeof(PeoInfo));
if(ptr != NULL)
{
pcon->data = ptr;
pcon->capacity *= 2;
printf("增容成功\n");
}
}
}
- 再者,动态开辟空间后,需要对其进行释放,于是需增加该函数。
void DestroyContact(Contact* pcon)
{
free(pcon->data);
pcon->data = NULL;
pcon->capacity = 0;
pcon->sz = 0;
}
- 最后,在之前代码的基础上,很容易能想到要在***增加***、***初始化***等步骤进行修改,这里便不再详细说明了,接下来我会给出全部代码,大家一看便知。
contact.h
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
#include<errno.h>
enum Option
{
Exit,
add,
del,
search,
modify,
show,
clear,
sort,
};
#define DEFAULT_SZ 3
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 12
#define ADDR_MAX 25
typedef struct Peoinfo
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char tele[TELE_MAX];
char addr[ADDR_MAX];
}Peoinfo;
typedef struct contact
{
struct Peoinfo *data;
int capacity;
int sz;
}contact;
void initcontact(contact* pcon);
void addcontact(contact* pcon);
void delcontact(contact* pcon);
void findcontact(contact* pcon);
void modifycontact(contact* pcon);
void showcontact(const contact* pcon);
void clearcontact(contact* pcon);
void sortcontact(contact* pcon);
void checkcapacity(contact* pcon);
void destroycontact(contact* pcon);
contact.c
#include"contact.h"
void initcontact(contact* pcon)
{
pcon->data = (Peoinfo *)malloc(DEFAULT_SZ*sizeof(Peoinfo));
if (pcon->data == NULL)
{
return;
}
pcon->sz = 0;
pcon->capacity = DEFAULT_SZ;
}
void checkcapacity(contact* pcon)
{
if (pcon->sz == pcon->capacity)
{
Peoinfo* ptr = realloc(pcon->data, (pcon->capacity * 2)*sizeof(Peoinfo));
if (ptr != NULL)
{
pcon->data = ptr;
pcon->capacity *= 2;
printf("增容成功\n");
}
else
{
printf("增容失败\n");
}
}
}
void addcontact(contact* pcon)
{
checkcapacity(pcon);
assert(pcon);
printf("请输入名字:>");
scanf("%s", pcon->data[pcon->sz].name);
printf("请输入年龄:>");
scanf("%d", &(pcon->data[pcon->sz].age));
printf("请输入性别:>");
scanf("%s", pcon->data[pcon->sz].sex);
printf("请输入电话:>");
scanf("%s", pcon->data[pcon->sz].tele);
printf("请输入地址:>");
scanf("%s", pcon->data[pcon->sz].addr);
pcon->sz++;
printf("增加成功\n");
}
static int findbyname(contact* pcon, char name[])
{
int i = 0;
assert(pcon);
for (i = 0; i < pcon->sz; i++)
{
if (0 == strcmp(pcon->data[i].name, name))
{
return i;
}
}
return -1;
}
void delcontact(contact* pcon)
{
int i = 0;
char name[NAME_MAX] = { 0 };
int pos = 0;
assert(pcon);
if (pcon->sz == 0)
{
printf("空通讯录,无法删除\n");
return;
}
printf("请输入要删除的姓名:");
scanf("%s", name);
pos = findbyname(pcon, name);
if (pos == -1)
{
printf("要删除的条目不在\n");
return;
}
for (i = pos; i < pcon->sz; i++)
{
pcon->data[i] = pcon->data[i + 1];
}
pcon->sz--;
printf("删除成功\n");
}
void findcontact(contact* pcon)
{
int i = 0;
char name[NAME_MAX] = { 0 };
int pos = 0;
assert(pcon);
if (pcon->sz == 0)
{
printf("空通讯录,无法删除\n");
return;
}
printf("请输入要删除的姓名:");
scanf("%s", name);
pos = findbyname(pcon, name);
if (pos == -1)
{
printf("要删除的条目不在\n");
return;
}
printf("%15s\t%5d\t%5s\t%12s\t%20s\n",
pcon->data[pos].name,
pcon->data[pos].age,
pcon->data[pos].sex,
pcon->data[pos].tele,
pcon->data[pos].addr);
}
void modifycontact(contact* pcon)
{
int i = 0;
char name[NAME_MAX] = { 0 };
int pos = 0;
assert(pcon);
if (pcon->sz == 0)
{
printf("空通讯录,无法修改\n");
return;
}
printf("请输入要修改的姓名:");
scanf("%s", name);
pos = findbyname(pcon, name);
if (pos == -1)
{
printf("要修改的条目不在\n");
return;
}
printf("请输入要修改的信息(1-姓名,2-年龄,3-性别, 4-电话, 5-地址)");
int msg;
scanf("%d", &msg);
switch (msg)
{
case 1:
printf("请输入要新的姓名:");
scanf("%s", pcon->data[pos].name);
break;
case 2:
printf("请输入要新的年龄:");
scanf("%s", pcon->data[pos].age);
break;
case 3:
printf("请输入要新的性别:");
scanf("%s", pcon->data[pos].sex);
break;
case 4:
printf("请输入要新的电话:");
scanf("%s", pcon->data[pos].tele);
break;
case 5:
printf("请输入要新的地址:");
scanf("%s", pcon->data[pos].addr);
break;
default:
printf("输入有误,修改失败\n");
return;
}
printf("修改成功\n");
}
void showcontact(const contact* pcon)
{
int i = 0;
assert(pcon);
printf("%15s\t%5s\t%5s\t%12s\t%20s\n", "名字", "年龄", "性别", "电话", "地址");
for (i = 0; i < pcon->sz; i++)
{
printf("%15s\t%5d\t%5s\t%12s\t%20s\n", pcon->data[i].name,
pcon->data[i].age,
pcon->data[i].sex,
pcon->data[i].tele,
pcon->data[i].addr);
}
}
void clearcontact(contact* pcon)
{
initcontact(pcon);
}
void sortcontact(contact* pcon)
{
int i, j;
Peoinfo tmp;
for (i = 0; i < pcon->sz - 1; i++)
{
for (j = 0; j < pcon->sz - 1 - i; j++)
{
if (0 < strcmp(pcon->data[j].name, pcon->data[j + 1].name))
{
tmp = pcon->data[j];
pcon->data[j] = pcon->data[j + 1];
pcon->data[j + 1] = tmp;
}
}
}
}
void destroycontact(contact* pcon)
{
free(pcon->data);
pcon->data = NULL;
pcon->capacity = 0;
pcon->sz = 0;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
void menu()
{
printf("***************************************\n");
printf("******1. add 2. del **********\n");
printf("******3. search 4. modify **********\n");
printf("******5. show 6. clear **********\n");
printf("******7. sort 0. exit **********\n");
}
int main()
{
int input = 0;
contact con;
initcontact(&con);
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case add:
addcontact(&con);
break;
case del:
delcontact(&con);
break;
case search:
findcontact(&con);
break;
case sort:
sortcontact(&con);
break;
case show:
showcontact(&con);
break;
case clear:
clearcontact(&con);
break;
case Exit:
destroycontact(&con);
printf("退出程序\n");
return 0;
default:
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}