目录
前言
改进通讯录的类型
改进初始化函数
改进添加联系人函数
增加销毁通讯录信息的功能
完整代码
在此之前我们就已经实现了静态通讯录的一些功能,但是这个静态的通讯录的空间大小从开始就写定了,不能随意改变,例如我们给定大小为300个人的通讯录,但是我最多只有200个好友,其余的100个空间就相当于闲置浪费了,但是我们有些人跑业务需要500个甚至更多的空间,但是空间又不足。我们对于空间的需求大小,是程序运行时才知道,原来静态开辟的空间大小就不能够满足所需,我们便要进行动态开辟了。
于是我们就可以实现用多少,给多少的空间大小,既不会浪费空间也不会空间不足。
由于之前的静态通讯录比较详细,此篇重点讲解修改的地方
我们改进后的通讯录主要特点:
①:开始提供3个联系人大小的空间
②:需要添加联系人的时候扩容,每次扩容空间大小+2(也有常用的空间变为原来的2倍)
原来的通讯录类型:
struct Contact//大通讯录,可以记录很多人 { struct PeoInfo date[MAX];//嵌套结构体 //存放1000个人的信息 int size;//记录当前的联系人个数 };
现在的通讯录类型:
struct Contact//大通讯录,可以记录很多人 { struct PeoInfo * date;//date指针指向动态内存开辟的一块空间 int size;//记录当前的联系人个数 int capacity;//记录容量 };
既然我们需要动态内存开辟,我们必然少不了一个指向动态内存开辟的一个指针变量。而且随着联系人的增多,我们的容量就会慢慢变小,于是就会涉及到扩容问题,我们需要定义一个新的容量变量capacity。
void ContactInit(struct Contact* ps)//初始化通讯录,联系人个数置0 { //初始化开辟一块空间用malloc ps->date=(struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));//初始化3个联系人的空间 if (ps->date == NULL) { return; } ps->size = 0; ps->capacity = 3; }
用malloc函数开辟一块空间,返回给date指针。当前为初始化联系人个数为size=0,容量为capacity=3。
static int ContactCheck(struct Contact* ps)//检查当前通讯录是否已经满了,满了则扩容,扩容时失败则返回1 { if (ps->size == ps->capacity) { struct PeoInfo* ptr =(struct PeoInfo*) realloc(ps->date, ps->capacity+2);//用一个ptr指针来接收首地址 if (ptr != NULL) { ps->date = ptr; ps->date += 2; return 0;//成功扩容 } else { return 1;//扩容失败 } } } void ContactAdd(struct Contact* ps) { int flag = ContactCheck(ps); if (flag == 1) { printf("空间不足,增加失败\n"); return; } printf("请输入姓名:>"); scanf("%s", ps->date[ps->size].name); printf("请输入年龄:->"); scanf("%d", &(ps->date[ps->size].age)); printf("请输入性别:>"); scanf("%s", ps->date[ps->size].sex); printf("请输入电话号码:>"); scanf("%s", ps->date[ps->size].tele); printf("请输入地址:>"); scanf("%s", ps->date[ps->size].address); ps->size++; printf("添加成功\n"); }
老规矩我们要先检查通讯录是否已经满了,满了则扩容容量capacity加2,扩容时失败则返回1,记得size++。设置一个flag标记,让可读性更佳!
void DestroyContact(struct Contact* ps) { free(ps->data);//释放动态开辟空间 ps->data = NULL; }
除了添加函数ContactAdd和检查函数ContactCheck函数需要动态内存开辟外,其他的功能函数均不需要修改,但内存开辟最重要的一点就是就得内存释放,避免造成内存泄漏
test.dynamicContact.c:
#define _CRT_SECURE_NO_WARNINGS 1 #include"contact.h" void menu() { printf("************************\n"); printf("***** Contact *****\n"); printf("***** 0.Exit *****\n"); printf("***1.Add 2.Delete ***\n"); printf("***3.Search 4.Modify ***\n"); printf("***5.Show 6.Sort ***\n"); printf("************************\n"); printf("\n"); } int main() { int input = 0; struct Contact con;//con就是通讯录,就是记录1000个人和现有联系人个数 ContactInit(&con);//初始化 do { menu(); printf("请输入数字来选择接下来的操作:>"); scanf("%d", &input); switch (input) { case ADD: //case 1: ContactAdd(&con); break; case DELETE: ContactDelete(&con); break; case SEARCH: ContactSearch(&con); break; case MODIFY: ContactModify(&con); break; case SHOW: ContactShow(&con); break; case EXIT: printf("退出通讯录"); case SORT: ContactSort(&con); break; default: printf("选择错误,请重新选择"); break; } } while (input); return 0; }
contact.c :
#define _CRT_SECURE_NO_WARNINGS 1 #include"contact.h" void ContactInit(struct Contact* ps)//初始化通讯录,联系人个数置0 { //初始化开辟一块空间用malloc ps->date=(struct PeoInfo*)malloc(3 * sizeof(struct PeoInfo));//初始化3个联系人的空间 if (ps->date == NULL) { return; } ps->size = 0; ps->capacity = 3; } static int ContactCheck(struct Contact* ps)//检查当前通讯录是否已经满了,满了则扩容,扩容时失败则返回1 { if (ps->size == ps->capacity) { struct PeoInfo* ptr =(struct PeoInfo*) realloc(ps->date, ps->capacity+2);//用一个ptr指针来接收首地址 if (ptr != NULL) { ps->date = ptr; ps->date += 2; return 0;//成功扩容 } else { return 1;//扩容失败 } } } void ContactAdd(struct Contact* ps) { int flag = ContactCheck(ps); if (flag == 1) { printf("空间不足,增加失败\n"); return; } printf("请输入姓名:>"); scanf("%s", ps->date[ps->size].name); printf("请输入年龄:->"); scanf("%d", &(ps->date[ps->size].age)); printf("请输入性别:>"); scanf("%s", ps->date[ps->size].sex); printf("请输入电话号码:>"); scanf("%s", ps->date[ps->size].tele); printf("请输入地址:>"); scanf("%s", ps->date[ps->size].address); ps->size++; printf("添加成功\n"); } int FindByName(char name[MAX_NAME], const struct Contact* ps)//查找联系人,找到了返回下标,没找到返回-1 { int i = 0; for (i = 0; i < ps->size; i++) { if (strcmp(ps->date[i].name, name) == 0)//ps指针去找通讯录里的人,后一个name是输入的名字的指针 return i; } return -1; } void ContactDelete(struct Contact* ps) { char name[MAX_NAME]; printf("请输入要删除人的姓名:>"); scanf("%s", name); int pos = FindByName(name, ps); if (pos == -1) { printf("无此联系人\n"); } else { int i = 0; for (i = pos; i < ps->size - 1; i++) { ps->date[i] = ps->date[i + 1];//从要删除的联系人位置起,后一个联系人信息依次覆盖前一个联系人 } printf("删除成功\n"); ps->size--; } } void ContactSearch(const struct Contact* ps)//查找指定联系人并打印信息 { char name[MAX_NAME]; printf("请输入要删除人的姓名:>"); scanf("%s", name); int pos = FindByName(name, ps); if (pos == -1) { printf("无此联系人\n"); } else { printf("%-20s\t%-4s\t%-5s\t%-20s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址"); printf("%-20s\t%-4d\t%-5s\t%-20s\t%-20s\n", ps->date[pos].name, ps->date[pos].age, ps->date[pos].sex, ps->date[pos].tele, ps->date[pos].address); }//打印联系人的信息 } void ContactModify(struct Contact* ps) { char name[MAX_NAME]; printf("请输入要修改人的姓名:>"); scanf("%s", name); int pos = FindByName(name, ps); if (pos == -1) { printf("无此联系人\n"); } else { printf("请输入联系人姓名:>"); scanf("%s", ps->date[pos].name); printf("请输入年龄:>"); scanf("%d", &(ps->date[pos].age)); printf("请输入性别:>"); scanf("%s", ps->date[pos].sex); printf("请输入电话:>"); scanf("%s", ps->date[pos].tele); printf("请输入住址:>"); scanf("%s", ps->date[pos].address); printf("修改成功\n"); } } void ContactShow(struct Contact* ps)//打印联系人信息 { if (ps->size == 0) { printf("联系人为空\n"); } else { printf("%-20s\t%-4s\t%-5s\t%-20s\t%-20s\n", "姓名", "年龄", "性别", "电话", "住址"); //打印第一行信息栏 int i = 0; for (i = 0; i < ps->size; i++)//遍历打印所有的联系人信息 { printf("%-20s\t%-4d\t%-5s\t%-20s\t%-20s\n", ps->date[i].name, ps->date[i].age, ps->date[i].sex, ps->date[i].tele, ps->date[i].address); } } } int CmpByName(const void* e1, const void* e2) { return strcmp((const char*)e1, (const char*)e2); } void ContactSort(struct Contact* ps)//通过名字排序 { qsort(ps->date, ps->size, sizeof(struct PeoInfo), CmpByName); } //销毁通讯录 void ContactDestory(struct Contact* ps) { free(ps->date); ps->date = NULL; }
contact.h:
#define _CRT_SECURE_NO_WARNINGS 1 #pragma once #define MAX 1000 #define MAX_NAME 20 #define MAX_SEX 5 #define MAX_TELE 20 #define MAX_ADDRESS 20 #include <string.h> #include <stdlib.h> #include<stdio.h> enum Option//与结构体数组原理相同 { EXIT,//0 ADD,//1 DELETE,//2 SEARCH,//3 MODIFY, SHOW, SORT }; struct PeoInfo//每个联系人的信息 { char name[MAX_NAME]; int age; char sex[MAX_SEX]; int tele[MAX_TELE]; char address[MAX_ADDRESS]; }; struct Contact//大通讯录,可以记录很多人 { struct PeoInfo * date;//date指针指向动态内存开辟的一块空间 int size;//记录当前的联系人个数 int capacity;//记录容量 }; void ContactInit(struct Contact* ps); void ContactAdd(struct Contact* ps); int FindByName(char name[MAX_NAME], const struct Contact* ps); void ContactDelete(struct Contact* ps); void ContactSearch(const struct Contact* ps); void ContactModify(struct Contact* ps); void ContactShow(struct Contact* ps); int CmpByName(const void* e1, const void* e2); void ContactSort(struct Contact* ps); void ContactDestory(struct Contact* ps);
谢谢各位博友的支持!