静态版的通讯录实现会出现一个问题就是我们一开始就创建了一个1000容量的通讯录,这样会使得空间极大的浪费,也有可能会出现以下的问题,因此我们考虑动态开辟内存空间,根据用户的实时情况来进行扩容等问题。
一共三个文件:头文件、通讯录函数源文件、主函数源文件。
1)头文件:用来进行函数声明、以及类型的定义。
2)通讯录函数文件:用来实现我们所需要的函数的。
3)主函数文件:程序逻辑实现、编译执行的文件。
void menu()
{
printf("****************************************\n");
printf("******** 1.add 2.del **********\n");
printf("******** 3.search 4.modify **********\n");
printf("******** 0.quit **********\n");
printf("****************************************\n");
printf("****************************************\n");
}
主函数内使用dowhile循环体来实现这样的一个循环,具体的不同功能,采用了switch语句,通过输入不同数值来进入不同的功能区,由于需要对堆区开辟的空间进行释放,在静态实现的基础上增加了destroy_contact函数
int main()
{
int input = 0;
//定义通讯录
Contact con;
//初始化
init_contact(&con);
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case add:
addcontact(&con);
print(&con);
break;
case del:
delcontact(&con);
print(&con);
break;
case search:
searchcontact(&con);
break;
case modify:
modifycontact(&con);
print(&con);
break;
case quit:
destroy_contact(&con);
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (input);
return 0;
}
typedef struct Contact //建立通讯录
{
contact* data ;
int capacity ;
int sz;
}Contact;
首先我们应该在堆区开辟一定的空间,假设我们先取3个struct contact大小的空间,那么我们怎么去调用这片空间呢?因为动态内存开辟空间函数返回的均是一个指针,因此我们理所应当的想到用一个指针来指向这段空间,所以创建了contact* data ,由于随着通讯录成员的随时增加,我们也应该知道它实时的容量的一个动态所以创建了int capacity。
void init_contact(Contact* pd) //初始化
{
pd->data = (contact*)calloc(INITMAX, sizeof(contact));
if (pd->data == NULL)
{
perror("init_contact");
return;
}
pd->sz = 0;
pd->capacity = INITMAX;
}
与静态唯一不同的是就是动态开辟内存空间函数的使用,具体可看上篇博客内容。
void addcontact(Contact* pa) //增加用户信息
{
if (pa->sz == pa->capacity)
{
printf("成员已满,扩容中\n");
contact* p = (contact*)realloc(pa->data,(INITMAX + ADDPEO)* sizeof(contact));
if (p == NULL)
{
printf("扩容失败\n");
return;
}
else
{
pa->data = p;
pa->capacity = pa->capacity + ADDPEO;
printf("扩容成功,请输入信息:\n");
}
}
printf("请输入名字:");
scanf("%s", &pa->data[pa->sz].name);
printf("请输入性别:");
scanf("%s", &pa->data[pa->sz].sex);
printf("请输入年龄:");
scanf("%d", &pa->data[pa->sz].age);
printf("请输入电话:");
scanf("%s", &pa->data[pa->sz].tele);
printf("请输入地址:");
scanf("%s", &pa->data[pa->sz].address);
pa->sz++;
printf("输入完成\n");
}
增加用户信息功能是与静态版的主要的不同,其实也就是realloc函数的使用,我们在此处每次扩容增加2个容量,如果要改变需要在头文件中所定义的常量ADDPEO中进行修改,需要注意pa->data,pa->capacity的调整
void print(const Contact* p) //打印用户
{
int i = 0;
//标题
printf("%-10s\t%-5s\t%-5s\t%-8s\t%-8s\n", "名称","性别","年龄","电话","地址");
for (i = 0; i < p->sz; i++)
{
printf("%-10s\t", p->data[i].name);
printf("%-5s\t", p->data[i].sex);
printf("%-5d\t", p->data[i].age);
printf("%-8s\t", p->data[i].tele);
printf("%-8s\t", p->data[i].address);
printf("\n");
}
}
打印用户函数与静态版完全类似,地址加减整数跳过的是相应的几个类型,因此可以看作与数组类似的一个效果,因此写成与静态版数组调用的形式
void searchcontact(const Contact* ps) //查找用户信息
{
int i = 0;
char sech[10] = { 0 };
printf("请输入要查找的用户名称:");
scanf("%s", &sech);
for (i = 0; i < ps->sz; i++)
{
if (strcmp(sech, ps->data[i].name) == 0)
{
printf("找到了\n");
break;
}
}
if (i == ps->sz)
{
printf("没找到\n");
}
}
void delcontact(Contact* pd) //删除用户信息
{
if (pd->sz == 0)
{
printf("通讯录内无用户\n");
}
char del[10] = { 0 };
printf("请输入要删除的用户名称:");
scanf("%s", &del);
for (int i = 0; i < pd->sz; i++)
{
if (strcmp(del, pd->data[i].name) == 0)
{
for (; i < pd->sz; i++)
{
pd->data[i] = pd->data[i + 1];
}
}
}
pd->sz--;
printf("删除成功\n");
}
void modifycontact(Contact* pm) //修改用户信息
{
int i = 0;
char modify[10] = { 0 };
printf("请输入要修改的用户名称:");
scanf("%s", &modify);
for (i = 0; i < pm->sz; i++)
{
if (strcmp(modify, pm->data[i].name) == 0)
{
printf("请输入名字:");
scanf("%s", &pm->data[i].name);
printf("请输入性别:");
scanf("%s", &pm->data[i].sex);
printf("请输入年龄:");
scanf("%d", &pm->data[i].age);
printf("请输入电话:");
scanf("%s", &pm->data[i].tele);
printf("请输入地址:");
scanf("%s", &pm->data[i].address);
printf("修改成功\n");
break;
}
}
if (i == pm->sz)
{
printf("无此用户\n");
}
}
void destroy_contact(Contact* pq)
{
free(pq->data);
pq->data = NULL;
}
由于我们在堆区上开辟空间,因此要及时地进行释放,以免导致各种各样的问题。
#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("******** 0.quit **********\n");
printf("****************************************\n");
printf("****************************************\n");
}
enum Option
{
quit ,
add,
del,
search,
modify,
};
int main()
{
int input = 0;
//定义通讯录
Contact con;
//初始化
init_contact(&con);
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case add:
addcontact(&con);
print(&con);
break;
case del:
delcontact(&con);
print(&con);
break;
case search:
searchcontact(&con);
break;
case modify:
modifycontact(&con);
print(&con);
break;
case quit:
destroy_contact(&con);
break;
default:
printf("输入错误,请重新输入:\n");
break;
}
} while (input);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
//动态版
void init_contact(Contact* pd) //初始化
{
pd->data = (contact*)calloc(INITMAX, sizeof(contact));
if (pd->data == NULL)
{
perror("init_contact");
return;
}
pd->sz = 0;
pd->capacity = INITMAX;
}
//静态版
//void init_contact(Contact* pd) //初始化
//{
// pd->sz = 0;
// memset(pd->data, 0, sizeof(pd->data));
//}
void destroy_contact(Contact* pq)
{
free(pq->data);
pq->data = NULL;
}
void print(const Contact* p) //打印用户
{
int i = 0;
//标题
printf("%-10s\t%-5s\t%-5s\t%-8s\t%-8s\n", "名称","性别","年龄","电话","地址");
for (i = 0; i < p->sz; i++)
{
printf("%-10s\t", p->data[i].name);
printf("%-5s\t", p->data[i].sex);
printf("%-5d\t", p->data[i].age);
printf("%-8s\t", p->data[i].tele);
printf("%-8s\t", p->data[i].address);
printf("\n");
}
}
//静态版
//void addcontact(Contact* pa) //增加用户信息
//{
// if (pa->sz >= MAX)
// {
// printf("通讯录已满");
// return;
// }
// printf("请输入名字:");
// scanf("%s", &pa->data[pa->sz].name);
// printf("请输入性别:");
// scanf("%s", &pa->data[pa->sz].sex);
// printf("请输入年龄:");
// scanf("%d", &pa->data[pa->sz].age);
// printf("请输入电话:");
// scanf("%s", &pa->data[pa->sz].tele);
// printf("请输入地址:");
// scanf("%s", &pa->data[pa->sz].address);
// pa->sz++;
// printf("输入完成\n");
//}
//动态版
void addcontact(Contact* pa) //增加用户信息
{
if (pa->sz == pa->capacity)
{
printf("成员已满,扩容中\n");
contact* p = (contact*)realloc(pa->data,(INITMAX + ADDPEO)* sizeof(contact));
if (p == NULL)
{
printf("扩容失败\n");
return;
}
else
{
pa->data = p;
pa->capacity = pa->capacity + ADDPEO;
printf("扩容成功,请输入信息:\n");
}
}
printf("请输入名字:");
scanf("%s", &pa->data[pa->sz].name);
printf("请输入性别:");
scanf("%s", &pa->data[pa->sz].sex);
printf("请输入年龄:");
scanf("%d", &pa->data[pa->sz].age);
printf("请输入电话:");
scanf("%s", &pa->data[pa->sz].tele);
printf("请输入地址:");
scanf("%s", &pa->data[pa->sz].address);
pa->sz++;
printf("输入完成\n");
}
void searchcontact(const Contact* ps) //查找用户信息
{
int i = 0;
char sech[10] = { 0 };
printf("请输入要查找的用户名称:");
scanf("%s", &sech);
for (i = 0; i < ps->sz; i++)
{
if (strcmp(sech, ps->data[i].name) == 0)
{
printf("找到了\n");
break;
}
}
if (i == ps->sz)
{
printf("没找到\n");
}
}
void delcontact(Contact* pd) //删除用户信息
{
if (pd->sz == 0)
{
printf("通讯录内无用户\n");
}
char del[10] = { 0 };
printf("请输入要删除的用户名称:");
scanf("%s", &del);
for (int i = 0; i < pd->sz; i++)
{
if (strcmp(del, pd->data[i].name) == 0)
{
for (; i < pd->sz; i++)
{
pd->data[i] = pd->data[i + 1];
}
}
}
pd->sz--;
printf("删除成功\n");
}
void modifycontact(Contact* pm) //修改用户信息
{
int i = 0;
char modify[10] = { 0 };
printf("请输入要修改的用户名称:");
scanf("%s", &modify);
for (i = 0; i < pm->sz; i++)
{
if (strcmp(modify, pm->data[i].name) == 0)
{
printf("请输入名字:");
scanf("%s", &pm->data[i].name);
printf("请输入性别:");
scanf("%s", &pm->data[i].sex);
printf("请输入年龄:");
scanf("%d", &pm->data[i].age);
printf("请输入电话:");
scanf("%s", &pm->data[i].tele);
printf("请输入地址:");
scanf("%s", &pm->data[i].address);
printf("修改成功\n");
break;
}
}
if (i == pm->sz)
{
printf("无此用户\n");
}
}
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_TELE 20
#define MAX_ADDRESS 20
#define MAX 1000
#define INITMAX 3
#define ADDPEO 2
typedef struct contact
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char tele[MAX_TELE];
char address[MAX_ADDRESS];
}contact;
//静态版
//typedef struct Contact //建立通讯录
//{
// contact data[MAX];
// int capacity;
// int sz;
//}Contact;
//动态版
typedef struct Contact //建立通讯录
{
contact* data ;
int capacity ;
int sz;
}Contact;
void print(const Contact* p);
void init_contact(Contact* pd);
void addcontact(Contact* pa);
void searchcontact(const Contact* ps);
void delcontact(Contact* pd);
void modifycontact(Contact* pm);
void destroy_contact(Contact* pq);