一.动态通讯录的设计
在之前已经实现静态的通讯录,接下来要对静态通讯录进行改造,将通讯录变成可以动态增长空间。
二、通讯录的改造
2.1 通讯录结构体改造
data是用于指向联系人的指针,sz是通讯录当前的长度,capacity是通讯录的最大容量。
typedef struct Contact
{
PeoInfo* data;
int sz;
int capacity; //最大容量
}Contact;
2.2 初始化通讯录功能的改造
先判断指针是否可用,再给指针的data开辟默认大小的空间,将长度和最大容量设为默认值。
void InitContact(Contact* p)
{
assert(p);
p->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
if (p->data == NULL)
{
perror("InitContact");
return;
}
p->sz = 0;
p->capacity = DEFAULT_SZ;
}
2.3 添加联系人功能的改造
设计一个判断空间是否已满的函数若已满则用realloc函数修改空间的大小,扩容成功后调整最大容量大小,再给通讯录添加联系人。
int CheckCapacity(Contact* p)
{
if (p->sz == p->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(p->data,(p->capacity + ADD_SZ) * sizeof(PeoInfo));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;
}
else
{
p->data = ptr;
p->capacity += ADD_SZ;
printf("扩容成功\n");
return 1;
}
}
return 1;
}
void AddContach(Contact* p)
{
assert(p);
if (CheckCapacity(p) == 0)
{
return;
}
printf("请输入姓名:");
scanf("%s", p->data[p->sz].name);
printf("请输入年龄:");
scanf("%d", &(p->data[p->sz].age));
printf("请输入性别:");
scanf("%s", p->data[p->sz].sex);
printf("请输入电话:");
scanf("%s", p->data[p->sz].tele);
printf("请输入地址:");
scanf("%s", p->data[p->sz].addr);
p->sz++;
printf("成功添加联系人\n");
}
三、添加的通讯录功能
因为不对开辟的空间释放会导致内存泄漏等问题,因此要设计一个函数用于释放内存。
void DestroyContact(Contact* p)
{
free(p->data);
p->data = NULL;
p->capacity = 0;
p->sz = 0;
}
四、代码一览
4.1 test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
void menu()
{
printf("***********************************\n");
printf("**** 1.添加 2.删除 *********\n");
printf("**** 3.查找 4.修改 *********\n");
printf("**** 5.显示 6.排序 *********\n");
printf("**** 0.退出 *********\n");
printf("***********************************\n");
}
void test()
{
int input = 0;
Contact con;
InitContact(&con);
do
{
menu();
printf("请选择操作:");
scanf("%d", &input);
switch (input)
{
case 1:
AddContach(&con);
break;
case 2:
DelContach(&con);
break;
case 3:
SearchContach(&con);
break;
case 4:
ModifyContach(&con);
break;
case 5:
ShowContach(&con);
break;
case 6:
SortContach(&con);
break;
case 0:
DestroyContact(&con);
printf("已退出!\n");
break;
default:
printf("输入错误请重新输入!\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
4.2 contact.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include<stdlib.h>
#define MAX 100 //通讯录大小
#define MAX_name 30
#define MAX_sex 5
#define MAX_tele 12
#define MAX_addr 40
#define DEFAULT_SZ 3
#define ADD_SZ 2
//声明结构体类型
typedef struct PeoInfo
{
char name[MAX_name];
int age;
char sex[MAX_sex];
char tele[MAX_tele];
char addr[MAX_addr];
}PeoInfo;
//通讯录
//静态版本
//typedef struct Contact
//{
// PeoInfo data[MAX];
// int sz;
//}Contact;
typedef struct Contact
{
PeoInfo* data;
int sz;
int capacity; //最大容量
}Contact;
//函数声明
//初始化通讯录
void InitContact(Contact *p);
//添加联系人信息
void AddContach(Contact* p);
//显示联系人信息
void ShowContach(Contact* p);
//删除联系人信息
void DelContach(Contact* p);
//查找联系人
void SearchContach(const Contact* p);
//修改联系人信息
void ModifyContach(Contact* p);
//按姓名排序联系人
void SortContach(Contact* p);
//释放
void DestroyContact(Contact* p);
4.3 contact.c
#include "contact.h"
int CheckCapacity(Contact* p);
//静态初始化
//void InitContact(Contact* p)
//{
// assert(p);
// for (int i = 0; i < MAX; i++)
// {
// strcpy(p->data[i].name, "0");
// p->data[i].age=0;
// strcpy(p->data[i].sex, "0");
// strcpy(p->data[i].addr, "0");
// strcpy(p->data[i].tele, "0");
// }
// p->sz= 0;
//}
//动态初始化
void InitContact(Contact* p)
{
assert(p);
p->data = (PeoInfo*)malloc(DEFAULT_SZ * sizeof(PeoInfo));
if (p->data == NULL)
{
perror("InitContact");
return;
}
p->sz = 0;
p->capacity = DEFAULT_SZ;
//加载
LoadContact(p);
}
//扩容
int CheckCapacity(Contact* p)
{
if (p->sz == p->capacity)
{
PeoInfo* ptr = (PeoInfo*)realloc(p->data,(p->capacity + ADD_SZ) * sizeof(PeoInfo));
if (ptr == NULL)
{
perror("CheckCapacity");
return 0;
}
else
{
p->data = ptr;
p->capacity += ADD_SZ;
printf("扩容成功\n");
return 1;
}
}
return 1;
}
//静态版本
//void AddContach(Contact* p)
//{
// assert(p);
// if (p->sz == MAX)
// {
// printf("通讯录已满,无法添加!\n");
// return;
// }
// printf("请输入姓名:");
// scanf("%s", p->data[p->sz].name);
// printf("请输入年龄:");
// scanf("%d", &(p->data[p->sz].age));
// printf("请输入性别:");
// scanf("%s", p->data[p->sz].sex);
// printf("请输入电话:");
// scanf("%s", p->data[p->sz].tele);
// printf("请输入地址:");
// scanf("%s", p->data[p->sz].addr);
//
//
// p->sz++;
// printf("成功添加联系人\n");
//}
//动态版本
void AddContach(Contact* p)
{
assert(p);
if (CheckCapacity(p) == 0)
{
return;
}
printf("请输入姓名:");
scanf("%s", p->data[p->sz].name);
printf("请输入年龄:");
scanf("%d", &(p->data[p->sz].age));
printf("请输入性别:");
scanf("%s", p->data[p->sz].sex);
printf("请输入电话:");
scanf("%s", p->data[p->sz].tele);
printf("请输入地址:");
scanf("%s", p->data[p->sz].addr);
p->sz++;
printf("成功添加联系人\n");
}
void ShowContach(Contact* p)
{
assert(p);
printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
for (int i = 0; i < p->sz; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
p->data[i].name,
p->data[i].age,
p->data[i].sex,
p->data[i].tele,
p->data[i].addr);
}
}
static int Findname(const Contact* p, char name[])
{
int i = 0;
for (i = 0; i < p->sz; i++)
{
if (strcmp(p->data[i].name, name) == 0)
{
return i; //找到
}
}
return -1; //没找到
}
void DelContach(Contact* p)
{
assert(p);
if (p->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[MAX_name] = {0};
printf("请输入删除人的名字:");
scanf("%s", name);
/*int i = 0;
int del = 0;
int flag = 0;
for (i = 0; i < p->sz;i++)
{
if (strcmp(p->data[i].name, name)==0)
{
del = i;
flag = 1;
break;
}
}
if (flag == 0)
{
printf("没有此人\n");
return;
}*/
int del = Findname(p, name);
if(del == -1)
{
printf("没有此人\n");
return;
}
int i = 0;
for (i = del; i < p->sz - 1; i++)
{
p->data[i] = p->data[i + 1];
}
printf("成功删除\n");
p->sz--;
}
void SearchContach(const Contact* p)
{
assert(p);
char name[MAX_name];
printf("请输入查找人的名字:");
scanf("%s", name);
int sear = Findname(p, name);
if (sear == -1)
printf("没有此人");
else
printf("%-10s\t%-4d\t%-5s\t%-12s\t%-30s\n",
p->data[sear].name,
p->data[sear].age,
p->data[sear].sex,
p->data[sear].tele,
p->data[sear].addr);
}
void ModifyContach(Contact* p)
{
assert(p);
char name[MAX_name];
printf("请输入修改人的名字:");
scanf("%s", name);
int modi = Findname(p, name);
if (modi == -1)
printf("没有此人");
else
{
printf("请输入姓名:");
scanf("%s", p->data[modi].name);
printf("请输入年龄:");
scanf("%d", &(p->data[modi].age));
printf("请输入性别:");
scanf("%s", p->data[modi].sex);
printf("请输入电话:");
scanf("%s", p->data[modi].tele);
printf("请输入地址:");
scanf("%s", p->data[modi].addr);
printf("修改成功\n");
}
}
void SortContach(Contact* p)
{
assert(p);
if (p->sz == 0)
{
printf("表空,无法排序\n");
return;
}
PeoInfo temp;
int i = 0;
int j = 0;
for (i = 0; i < p->sz; i++)
{
for(j = 0; j < p->sz - i - 1; j++)
{
if (strcmp(p->data[j].name, p->data[j + 1].name) > 0)
{
temp = p->data[j];
p->data[j] = p->data[j + 1];
p->data[j + 1] = temp;
}
}
}
printf("排序成功\n");
}
void DestroyContact(Contact* p)
{
free(p->data);
p->data = NULL;
p->capacity = 0;
p->sz = 0;
}