目录
假设初始容量为 3 个人的信息,
当容量不够时,进行扩容,每次扩容增添 2 个人的信息。
1.创建通讯录
此时需要更改创建的通讯录,使其变得可以更改。
typedef struct contact
{
Peopleone* data;//data 指向了存放数据的空间
int sum;//记录通讯录中的有效信息个数
int capacity;//通讯录当前的容量
}Contact;
2.初始化通讯录
在初始化通讯录时,要使用 malloc 开辟空间
malloc
头文件: #include<stdlib.h>
在该通讯录中,类型为 Peopleone(结构体类型),
最初时,通讯录中有 3 (#define DEFAULT_SZ 3 //初始容量为3人)个人的信息。
所以开辟的大小为:
(Peopleone*) malloc(DEFAULT_SZ * sizeof(Peopleone))
放到 pc-> data 中。
即初始化代码为:
//动态版本
void InitContact(Contact* pc)
{
pc->data = (Peopleone*) malloc(DEFAULT_SZ * sizeof(Peopleone));
if (pc->data == NULL)
{
printf("通讯录初始化失败—> %s\n", strerror(errno));
return;
}
pc->sum = 0;
pc->capacity = DEFAULT_SZ;
printf("初始化通讯录成功\n");
}
3.增加联系人
当添加联系人,有可能当前通讯录中的有效信息个数等于当前通讯录的容量,此时需要进行扩容,使用 realloc 函数。
realloc
头文件:#include<stdlib.h>
若扩容失败,打印失败原因,
若扩容成功,需输出增容成功,已经当前容量。
然后输入新建联系人的信息,通讯录中的有效信息人数加一,并输出添加成功。
即增加联系人的代码如下:
//若扩容失败,返回值为0
//扩容成功,或者不需要扩容,返回值为 1
int CheckCapacity(Contact* pc)
{
//通讯录中的有效信息人数 等于 通讯录当前的容量
if (pc->sum == pc->capacity)
{
Peopleone* ptr = (Peopleone*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(Peopleone));
if (ptr == NULL)
{
printf("CheckCapacity:% s\n", strerror(errno));
return 0;
}
else
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功,当前容量为:%d\n", pc->capacity);
return 1;
}
}
return 1;
}
//动态版本
void ADDContact(Contact* pc)
{
if (0 == CheckCapacity(pc))
{
printf("空间不足,扩容失败\n");
return;
}
else
{
printf("请输入新建联系人的名字->");
scanf("%s", pc->data[pc->sum].name);
printf("请输入新建联系人的性别->");
scanf("%s", pc->data[pc->sum].sex);
printf("请输入新建联系人的年龄->");
scanf("%d", &(pc->data[pc->sum].age));
//当输入新建联系人的年龄时,需要 &
printf("请输入新建联系人的手机号码->");
scanf("%s", pc->data[pc->sum].phone);
printf("请输入新建联系人的住址->");
scanf("%s", pc->data[pc->sum].address);
//添加成功后,通讯录中的有效信息数 + 1
pc->sum++;
printf("添加成功\n");
}
}
效果为:
4.完整的代码
contact.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#define MAX 100
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_PHONE 20
#define MAX_ADDRESS 30
#define DEFAULT_SZ 3 //初始容量为3人
#define INC_SZ 2 //每次扩容增加 2 个
//一个人的信息
typedef struct ID
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char phone[MAX_PHONE];
char address[MAX_ADDRESS];
}Peopleone;//结构体类型
/*
typedef struct
{
int a;
char b;
}S;//结构体类型 --- 类型名
struct Stu // 定义一个学生类型
{
//成员变量
char name[20];
int age;
}s;//结构体变量
*/
//动态版本
//1.默认能够存放 3 个人的信息
//2.不够的时候,默认每次增加 2 个人的信息
typedef struct contact
{
Peopleone* data;//data 指向了存放数据的空间
int sum;//记录通讯录中的有效信息个数
int capacity;//通讯录当前的容量
}Contact;
//初始化通讯录
void InitContact(Contact* pc);
//添加联系人
void ADDContact(Contact* pc);
//展示通讯录
void SHOWContact(const Contact* pc);
//展示通讯录时,不会改变通讯录里的内容,加上 const 更加安全
//删除指定联系人
void DELContact(Contact* pc);
//查找联系人
void SEEKContact(const Contact* pc);
//修改指定联系人
void REVISEContact(Contact* pc);
//排序联系人
void SORTContact(Contact* pc);
//销毁通讯录
void EXITContace(Contact* pc);
tast.c
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
void menu()
{
printf("**************************************\n");
printf("****** 1. ADD 2. DEL ******\n");
printf("****** 3. SEEK 4.REVISE ******\n");
printf("****** 5.SHOW 6.SORT ******\n");
printf("******* 0. EXIT *******\n");
printf("**************************************\n");
}
enum NUM
{
EXIT,//0 销毁通讯录
ADD,//1 添加联系人
DEL,//2 删除指定联系人
SEEK,//3 查找指定联系人
REVISE,//4 修改通讯录
SHOW,//5 展示通讯录
SORT,//6 排序通讯录
};
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 SEEK:
SEEKContact(&con);
break;
case REVISE:
REVISEContact(&con);
break;
case SHOW:
SHOWContact(&con);
break;
case SORT:
SORTContact(&con);
break;
case EXIT:
EXITContace(&con);
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
contact.c
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
//动态版本
void InitContact(Contact* pc)
{
pc->data = (Peopleone*) malloc(DEFAULT_SZ * sizeof(Peopleone));
if (pc->data == NULL)
{
printf("通讯录初始化失败—> %s\n", strerror(errno));
return;
}
pc->sum = 0;
pc->capacity = DEFAULT_SZ;
printf("初始化通讯录成功\n");
}
//若扩容失败,返回值为0
//扩容成功,或者不需要扩容,返回值为 1
int CheckCapacity(Contact* pc)
{
//通讯录中的有效信息人数 等于 通讯录当前的容量
if (pc->sum == pc->capacity)
{
Peopleone* ptr = (Peopleone*)realloc(pc->data, (pc->capacity + INC_SZ) * sizeof(Peopleone));
if (ptr == NULL)
{
printf("CheckCapacity:% s\n", strerror(errno));
return 0;
}
else
{
pc->data = ptr;
pc->capacity += INC_SZ;
printf("增容成功,当前容量为:%d\n", pc->capacity);
return 1;
}
}
return 1;
}
//动态版本
void ADDContact(Contact* pc)
{
if (0 == CheckCapacity(pc))
{
printf("空间不足,扩容失败\n");
return;
}
else
{
printf("请输入新建联系人的名字->");
scanf("%s", pc->data[pc->sum].name);
printf("请输入新建联系人的性别->");
scanf("%s", pc->data[pc->sum].sex);
printf("请输入新建联系人的年龄->");
scanf("%d", &(pc->data[pc->sum].age));
//当输入新建联系人的年龄时,需要 &
printf("请输入新建联系人的手机号码->");
scanf("%s", pc->data[pc->sum].phone);
printf("请输入新建联系人的住址->");
scanf("%s", pc->data[pc->sum].address);
//添加成功后,通讯录中的有效信息数 + 1
pc->sum++;
printf("添加成功\n");
}
}
//展示通讯录
void SHOWContact(const Contact* pc)
{
int i = 0;
//打印表头 --- 表头为字符串 %s 打印
printf("%-20s %-10s %-4s %-20s %-30s\n", "姓名", "性别", "年龄", "电话", "住址");
// 加负号表示左对齐
for (i = 0; i < pc->sum; i++)
{
//打印年龄用 %d ,其余的用 %s
printf("%-20s %-10s %-4d %-20s %-30s\n",
pc->data[i].name,
pc->data[i].sex,
pc->data[i].age,
pc->data[i].phone,
pc->data[i].address);
//此时下标为 i
}
}
//查找要删除的联系人
int FindDel(const Contact* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->sum; i++)
{
//两个字符串进行比较用 strcmp 进行比较
if (strcmp(name, pc->data[i].name) == 0)
{
return i;
}
}
return -1;
}
//删除指定联系人
void DELContact(Contact* pc)
{
char name[MAX_NAME] = { 0 };
//判断通讯录是否为空,若通讯录为空,则无法删除
if (pc->sum == 0)
{
printf("通讯录为空,无法删除联系人\n");
return;
}
else
{
//删除指定联系人
printf("要删除的联系人的名字->");
scanf("%s",name);//自己输入要删除的人的名字
//查找要删除的联系人
int flag = FindDel(pc, name);
if (flag == -1)
{
printf("要删除的联系人不存在\n");
return;
}
else
{
//删除该联系人
int i = 0;
//删除 flag 上的数据
for (i = flag; i < pc->sum-1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sum--;
printf("删除成功\n");
}
}
}
//修改指定联系人
void REVISEContact(Contact* pc)
{
char name[MAX_NAME] = { 0 };
//修改指定联系人
printf("要修改的联系人的名字\n");
scanf("%s", name);
//查找要修改的联系人
int flag = FindDel(pc, name);
if (flag == -1)
{
printf("要修改的联系人不存在\n");
return;
}
else
{
//修改该联系人
//修改 flag 上的数据
printf("请输入修改后联系人的名字->");
scanf("%s", pc->data[flag].name);
printf("请输入修改后联系人的性别->");
scanf("%s",pc->data[flag].sex);
printf("请输入修改后联系人的年龄->");
scanf("%d",&( pc->data[flag].age));
printf("请输入修改后联系人的电话->");
scanf("%s", pc->data[flag].phone);
printf("请输入修改后联系人的地址->");
scanf("%s", pc->data[flag].address);
printf("修改成功\n");
}
}
int cmp_by_name(const void* e1, const void* e2)
{
return strcmp(((Peopleone*)e1)->name,((Peopleone*)e2)->name);
}
//排序联系人
void SORTContact(Contact* pc)
{
//qsort 排序函数
//void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
//#include <stdlib.h>
qsort(pc->data, pc->sum, sizeof(Peopleone), cmp_by_name);
printf("排序成功\n");
}
//查找联系人
void SEEKContact(const Contact* pc)
{
char name[MAX_NAME] = { 0 };
//查找指定联系人
printf("要的查找联系人的名字\n");
scanf("%s", name);
//查找联系人
int flag = FindDel(pc, name);
if (flag == -1)
{
printf("要查找的联系人不存在\n");
return;
}
else
{
printf("%-20s %-10s %-4s %-20s %-30s\n", "姓名", "性别", "年龄", "电话", "住址");
//打印年龄用 %d ,其余的用 %s
printf("%-20s %-10s %-4d %-20s %-30s\n",
pc->data[flag].name,
pc->data[flag].sex,
pc->data[flag].age,
pc->data[flag].phone,
pc->data[flag].address);
//此时下标为 flag
printf("查找成功\n");
}
}
void EXITContace(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->capacity = 0;
pc->sum = 0;
printf("释放内存.....\n");
}